Writing tests
Karva collects module-level Python functions whose names start with test by
default. Test files do not need a test_ prefix: Karva searches every .py
file under the selected paths and ignores files that contain no tests.
| tests/check_calculator.py | |
|---|---|
1 2 | |
Run the whole project, a directory, a file, or one function:
| Bash | |
|---|---|
1 2 3 4 | |
Use --test-prefix or test-function-prefix in configuration when your suite
uses another naming convention. Karva does not collect class methods; see
Project Non-Goals.
Project and path discovery
With no path arguments, Karva searches upward from the current directory for
karva.toml or a [tool.karva] table in pyproject.toml, then uses that
directory as the project root. If no Karva configuration exists, it uses the
nearest plain pyproject.toml, or the current directory when neither exists.
Discovery does not cross a .git boundary.
Karva respects .gitignore files by default. Pass --no-ignore to include
Git-ignored Python files, or set respect-ignore-files = false under the
profile's src configuration.
Test results
A passing test returns None, either explicitly or by reaching the end of the
function. Returning any other value fails the test with a diagnostic; use an
assertion instead.
Generator test functions are rejected before their bodies run. Use
@karva.tags.parametrize to create multiple cases.
Generator fixtures remain supported for setup and teardown.
Async tests and fixtures
Async tests run without a plugin or marker:
| tests/test_service.py | |
|---|---|
1 2 3 4 5 6 | |
Fixtures may also be async functions or async generators. Sync and async tests can consume either sync or async fixtures:
| tests/test_service.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Async generator fixture teardown is awaited after its consumer finishes, just
like teardown after yield in a sync fixture.
Background tasks
Work started with asyncio.create_task runs alongside the test. If it raises
and nothing awaits it, the exception never reaches the test coroutine, so
Python reports it to the event loop instead of propagating it. Karva watches
for those reports and fails the test:
| tests/test_service.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 | |
| Text Only | |
|---|---|
1 2 | |
Every unretrieved failure is reported, not only the first. The same watch covers async fixture setup and teardown, so a task started by a fixture is attributed to that fixture.
A failure the test deals with itself is not reported. Awaiting the task,
reading task.exception(), or collecting it through
asyncio.gather(..., return_exceptions=True) all count as handling it. Tasks
still pending when the test returns are cancelled cleanly during shutdown and
do not fail the test:
| Python | |
|---|---|
1 2 3 4 | |