Test Lifecycle Phases
k6 executes tests in the following order:1
Init Phase
Code in the init context runs once per VU at the beginning of the test.
2
Setup Phase
The
setup() function runs once before the test starts.3
VU Phase (Default Function)
The
default function executes repeatedly for each VU iteration.4
Teardown Phase
The
teardown() function runs once after the test completes.Init Context
The init context is where k6 prepares your test script. Code at the top level of your script runs during initialization.What Happens in Init
Based on the k6 source code ininternal/js/bundle.go, the init context:
- Imports modules
- Defines the
defaultfunction and options - Creates custom metrics
- Loads local files
- Initializes module-provided types
The init context runs once per VU. With 10 VUs, init code executes 10 times total.
Setup Phase
The optionalsetup() function runs once before the test begins, regardless of VU count.
Setup Use Cases
- Authenticate and obtain tokens
- Prepare test data
- Configure the system under test
- Retrieve configuration values
Default Function (VU Phase)
Thedefault function is the heart of your test. Each VU executes it repeatedly for the duration of the test.
Iteration Behavior
From the execution state implementation inlib/execution.go:
- Each VU is tracked with counters for full and interrupted iterations
fullIterationsCountincrements when iterations complete normallyinterruptedIterationsCountincrements when iterations are cut short- The
activeVUscounter tracks currently executing VUs
An iteration is the complete execution of the default function, from start to finish.
Teardown Phase
The optionalteardown() function runs once after all VUs finish executing.
Teardown Use Cases
- Clean up test data
- Log out or revoke tokens
- Reset system state
- Perform final validation
Execution Flow Diagram
Execution Status
k6 tracks test execution through multiple states defined inlib/execution.go:
ExecutionStatusCreated- Test createdExecutionStatusInitVUs- Initializing VUsExecutionStatusInitExecutors- Initializing executorsExecutionStatusInitDone- Initialization completeExecutionStatusSetup- Running setupExecutionStatusRunning- Default function executingExecutionStatusTeardown- Running teardownExecutionStatusEnded- Test complete
Best Practices
1
Keep Init Lightweight
Avoid expensive operations in init. Use it for imports and metric definitions only.
2
Use Setup for Authentication
Obtain tokens once in setup and distribute to VUs, rather than authenticating in every iteration.
3
Make Default Function Repeatable
Ensure the default function can run many times without side effects.
4
Handle Teardown Failures
Don’t rely on teardown for critical cleanup - it may not run if the test is interrupted.