Parallel execution
Karva runs tests in parallel Python worker processes. Tests in the same worker share an interpreter; tests in different workers do not.
Worker count
The default is one worker per CPU core. Override with -n / --num-workers:
| Bash | |
|---|---|
1 | |
Use --no-parallel (equivalent to -n 1) when debugging or testing shared
resources that cannot be partitioned:
| Bash | |
|---|---|
1 | |
Karva caps the worker count at the number of independently schedulable tests to avoid idle workers. It honours smaller requests without assuming how long each test takes. Worker-count reductions are logged at info level; the normal startup line shows the applied count.
Parametrized tests
Karva can distribute cases from one parametrized test across workers when the parameter values are written directly as a list or tuple literal:
| Python | |
|---|---|
1 2 3 | |
Values provided through a variable, comprehension, generator, or function call cannot be counted before a worker imports the module. Karva keeps those cases together on one worker:
| Python | |
|---|---|
1 2 3 4 5 | |
All cases still run; only their distribution across workers changes.
Partitioning shared resources
Give each worker its own database, port, or directory using KARVA_WORKER_ID:
| Python | |
|---|---|
1 2 3 4 5 6 | |
KARVA_WORKER_ID is 0-indexed and stable for the lifetime of the worker. See Environment Variables for the full list of variables the worker exposes to tests.
Output capture
By default, stdout/stderr from a test is captured and emitted only when the test fails or when --show-output / -s is set. This keeps parallel output legible — without capture, output from concurrent tests would interleave on the terminal.
While output is captured, stdin reads fail immediately with a diagnostic instead of waiting for terminal input. Pass input explicitly to code under test, or use --no-capture for an intentional interactive debugging session. Child processes receive an immediate end-of-file on stdin unless the test passes a pipe, file, or DEVNULL explicitly.
--no-capture disables capture entirely and forces a single worker, since uncaptured output from concurrent workers cannot safely interleave:
| Bash | |
|---|---|
1 | |
Use --no-capture for pdb or live output. Use -s / --show-output to
print every test's captured output while keeping parallel execution.
Splitting a run across CI jobs
--partition slice:M/N runs only slice M of N total slices. Tests are sorted by qualified name and distributed round-robin: test 1 to slice 1, test 2 to slice 2, ..., test N+1 to slice 1, and so on. Running every slice:1/N through slice:N/N together covers every collected test exactly once.
| Bash | |
|---|---|
1 2 3 | |
The same test set produces the same slices. Adding or removing tests can move other tests between slices.
Use hash:M/N when stable assignment matters more than even slices. Each
qualified test name maps to one stable bucket, so adding or removing a test
does not move any other test:
| Bash | |
|---|---|
1 2 3 | |
Hash buckets can be uneven. Run every bucket together to cover the complete suite.