Lifecycle Hooks
Inside a @suite, functions annotated with lifecycle hooks prepare and clean
up shared state without repeating code in each test.
| Decorator | When it runs |
|---|---|
@before_all |
Once before the first test |
@before_each |
Before each individual test |
@after_each |
After each individual test |
@after_all |
Once after the last test |
The example below uses a shared map state to demonstrate that @before_each
increments state.n once per test, @after_each records teardowns, and
@before_all runs exactly once for the entire suite:
Runs via zolo test. The second test validates the counters accumulated
by both hooks to prove execution order.
06-hooks.zolo
// Lifecycle hooks (T2): @before_each / @after_each / @before_all / @after_all.
//
// `before_each` runs before EACH test in the suite, so the shared counter
// `state.n` increments to 1 before `primeira` and to 2 before `segunda`.
@suite("contador")
mod hook_suite {
let state = #{ "n": 0, "torn_down": 0, "setup_all": 0 }
@before_all
fn open() { state.setup_all = state.setup_all + 1 }
@before_each
fn inc() { state.n = state.n + 1 }
@after_each
fn teardown() { state.torn_down = state.torn_down + 1 }
@test
fn primeira() { expect(state.n).to_eq(1) }
@test
fn segunda() {
// before_each ran twice; after_each ran once (after `primeira`);
// before_all ran exactly once.
expect(state.n).to_eq(2)
expect(state.torn_down).to_eq(1)
expect(state.setup_all).to_eq(1)
}
}
Requires the Zolo CLI/host — open in the playground or run locally.
Hooks have access to the same variables declared in the @suite module scope,
so state can be freely mutated between them and the tests.
See also