Coverage
Karva measures line coverage natively. There is no plugin to install, no .coveragerc, and no separate coverage binary on the path — coverage is part of karva test.
The implementation runs in the test worker on top of sys.monitoring (Python 3.12+) or sys.settrace (older versions), records every executed line under the configured source roots, and prints a Name / Stmts / Miss / Cover table at the end of the run.
Every coverage run also writes a coverage.py-compatible .coverage SQLite file in the project root. Tools such as coverage html, coverage xml, Codecov uploaders, IDE gutters, and diff-cover can consume that artifact directly.
Quick start
Pass --cov to measure the current working directory:
| Bash | |
|---|---|
1 | |
| Text Only | |
|---|---|
1 2 3 4 5 | |
Pass a path to limit measurement to specific source roots, or pass --cov multiple times to measure several:
| Bash | |
|---|---|
1 2 | |
Equivalent configuration:
| TOML | |
|---|---|
1 2 | |
An empty entry ("") measures the cwd, matching pytest-cov's bare --cov.
Branch coverage
Pass --cov-branch to measure branch destinations as well as lines:
| Bash | |
|---|---|
1 | |
| Text Only | |
|---|---|
1 2 3 4 5 | |
Branch coverage records line-to-line arcs for conditional control flow and compares them with statically possible branch destinations. The Cover percentage includes both statement and branch opportunities, matching coverage.py's branch coverage model. JSON, XML, HTML, and the .coverage SQLite file include branch data when branch mode is enabled.
Equivalent configuration:
| TOML | |
|---|---|
1 2 3 | |
Reports
--cov-report=term (the default) prints the compact table above. --cov-report=term-missing adds a Missing column listing the uncovered line numbers per file:
| Bash | |
|---|---|
1 | |
| Text Only | |
|---|---|
1 2 3 4 5 | |
--cov-report=xml[:PATH] writes Cobertura XML for CI integrations. If PATH is omitted, karva writes coverage.xml in the project root:
| Bash | |
|---|---|
1 2 | |
Equivalent configuration:
| TOML | |
|---|---|
1 2 3 4 | |
--cov-report=json[:PATH] writes a machine-readable JSON report. If PATH is omitted, karva writes coverage.json in the project root:
| Bash | |
|---|---|
1 2 | |
Pass --cov-context=test with JSON reports to include a contexts map from executed source lines to the qualified test names that covered them:
| Bash | |
|---|---|
1 | |
--cov-report=html[:DIR] writes a simple browsable HTML report. If DIR is omitted, karva writes htmlcov/ in the project root:
| Bash | |
|---|---|
1 2 | |
Files that were never imported during the run still appear, at 0%, so dead modules under your source root show up rather than silently inflating the total.
Filtering report files
Use --cov-include and --cov-omit to keep generated files, migrations, vendored code, or other non-target paths out of the report:
| Bash | |
|---|---|
1 | |
Globs match the project-relative file path shown in the coverage report. When include filters are set, only matching files are reported. Omit filters are applied after include filters.
Equivalent configuration:
| TOML | |
|---|---|
1 2 3 4 | |
Failing on low coverage
--cov-fail-under=N exits non-zero when total coverage drops below N, even if every test passed:
| Bash | |
|---|---|
1 | |
N accepts any value in 0..=100, fractional values included. The flag has no effect when tests already failed — the exit code is already non-zero in that case.
| TOML | |
|---|---|
1 2 | |
Disabling for a single run
--no-cov overrides any --cov flag and any [coverage] sources configured in karva.toml:
| Bash | |
|---|---|
1 | |
Use it when iterating locally without editing config — for example, to skip the tracer overhead on a tight feedback loop while CI keeps coverage on.
Excluding code
Append # pragma: no cover to a line to exclude it from the executable-line set:
| Python | |
|---|---|
1 2 3 4 | |
The pragma applies to the line it appears on. When placed on the head of a compound statement (def, class, if, elif, else, except, match, case, with, for, while, try), the entire body of that branch is excluded:
| Python | |
|---|---|
1 2 3 | |
The match is case-insensitive (# PRAGMA: NO COVER works) and is only recognised inside an actual comment — the literal text inside a string is not a directive.
Source roots
Every --cov value is canonicalised to an absolute path. A file is included in the report if its path lives under at least one source root and does not contain any of site-packages, dist-packages, .venv, or .tox — installed third-party code is filtered automatically.
Parallel runs
Each worker writes its own JSON file. After the run, the main process unions the per-file line sets and produces a single report. No coordination flag is required; coverage works the same with --no-parallel or with -n 16.
CI integration
A typical CI invocation pins a minimum and prints the missing lines:
| Bash | |
|---|---|
1 | |
For XML-consuming tools such as SonarQube or Codecov:
| Bash | |
|---|---|
1 | |
For machine-readable JSON or a browsable HTML summary:
| Bash | |
|---|---|
1 2 | |
Or, equivalently, in pyproject.toml:
| TOML | |
|---|---|
1 2 3 4 | |
| Bash | |
|---|---|
1 | |