Skip to main content
Flow tests can model any multi-step gameplay scenario. This guide covers patterns for structuring custom flows, handling edge cases, and making your flows robust and maintainable.

Basic Flow Structure

Every flow test follows the same fundamental pattern:
The cleanup step is handled automatically by IsolationStrategy.DEDICATED_WORLD.

Template

Design Patterns

The simplest flow: each step depends on the previous one, executed sequentially.
Some flows need to handle different outcomes depending on server behavior.
Test interactions between multiple entities.
Use awaitCondition to verify time-bounded behavior.

Best Practices

Keep flow tests focused on one scenario. A flow that tests spawning, combat, looting, crafting, and trading in a single method is hard to debug when it fails. Split it into smaller, targeted flows.

Use descriptive logging

Call ctx.log() at each major step. When a flow fails, the logs help you identify exactly where things went wrong.

Prefer awaitCondition over fixed waitTicks

Fixed tick waits are fragile - they may be too short on slow servers or unnecessarily long on fast ones. awaitCondition adapts automatically.

Use @Order for dependent flows

If flow tests in the same suite depend on each other (not recommended, but sometimes necessary), use @Order to enforce execution sequence.

Set appropriate timeoutTicks

Calculate the maximum expected duration of your flow and add a safety margin. At 30 TPS:
  • 100 ticks = ~3.3 seconds
  • 200 ticks = 10 seconds
  • 600 ticks = 30 seconds
Setting timeoutTicks too low will cause false failures on loaded servers. Setting it too high will make failed tests take a long time to report. Aim for 2-3x the expected duration.

Next Steps