pytest-cov review
pytest-cov 7.1.0 is the pytest adapter for coverage.py. It starts measurement with the test session, merges worker data, erases or appends coverage files, labels execution by test context, writes terminal and machine-readable reports, and can fail CI below a percentage. Coverage.py remains the measurement engine and owns most configuration. Version 7.1.0 fixes a serious CI inconsistency where report choices could change the total used by `--cov-fail-under`; it also corrects matching of escaped sqlite3 ResourceWarning filters.
pytest-cov 7.1.0 installed in 0.4 seconds and occupied 9 MB across 7 packages in our sandbox, with 0 audit findings. Add it when pytest should own coverage reporting and worker data; configure coverage.py explicitly for subprocesses and treat the percentage as a regression check, not a score for test quality.
We installed it
| Install | ✓ · 0.4s | 7 packages on disk · 9 MB |
| Import | ✓ | import pytest_cov in 0.55s · pure Python · requires Python >=3.9 |
| Known vulns | 0 | (pip-audit) |
Answers from our run
Does pytest-cov install cleanly?
Yes. In a fresh container with an empty cache, pip install pytest-cov finished in 0.4s, leaving 7 packages and 9 MB on disk. pip-audit reported no known vulnerabilities.
What does pytest-cov need to run?
Python >=3.9, and nothing compiled: it is pure Python. In our run import pytest_cov succeeded in 0.55s.
pytest-cov or coverage: which should you use?
coverage: Use coverage.py directly when pytest does not own the process or plugin behavior is unnecessary. pytest-cov 7.1.0 installed in 0.4 seconds and occupied 9 MB across 7 packages in our sandbox, with 0 audit findings.
When should you not use pytest-cov?
Tests run through unittest or another entry point; coverage.py can execute them without a pytest plugin
Use it if
- A pytest command should produce terminal, HTML, XML, JSON, LCOV, or Markdown coverage output
- CI needs one reproducible coverage floor shared with local pytest runs
- pytest-xdist workers must contribute execution data to the same final report
- Per-test contexts are needed to identify which test reaches a particular line
- Tests run through unittest or another entry point; coverage.py can execute them without a pytest plugin
- Child-process measurement is expected with zero config; pytest-cov 7 removed its automatic .pth startup mechanism
- A high percentage will be treated as proof of useful assertions; line execution cannot establish test quality
- The project has no single coverage configuration, because command flags can silently override source and branch settings
- Compiled native code must be measured; coverage.py records Python execution rather than paths inside an extension module
Setup reality
Our Python 3.12 sandbox installed pytest-cov 7.1.0 in 0.4 seconds. Seven packages occupied 9 MB, and pip-audit found 0 known vulnerabilities. Inspection found 6 direct dependencies, pure Python code, an MIT License, and a Python 3.9 minimum. import pytest_cov completed in 0.55 seconds. The distribution did not include py.typed. pytest and coverage.py arrive as runtime requirements.
No credentials are needed. Keep measurement policy in .coveragerc, pyproject.toml, setup.cfg, or tox.ini, then use a short pytest command. --cov=package replaces coverage.py's configured source selection; a bare --cov keeps those sources. Pass --cov-config for a nonstandard filename, especially when workers or subprocesses start from another directory. Decide branch mode and omit rules in the same file used by CI.
pytest-cov 7 removed the .pth file that used to begin measurement in child interpreters. Projects that spawn Python now enable coverage.py's subprocess patch under [run]; parallel data settings may also be necessary. pytest-xdist remains supported, including remote workers, but pytest-cov and compatible coverage.py versions must be installed in every worker environment. Non-Python child programs and native extension internals remain outside this measurement model.
A normal run erases existing coverage data before tests. Use --cov-append only when separate commands are intentionally combined. Adding XML or HTML reports can remove the default terminal report unless term or term-missing is also requested. --cov-context=test stores full pytest node IDs, including parametrized cases, and can enlarge the data file. Version 7.1.0 should be the minimum for a threshold gate because 7.0 report combinations could calculate different totals.
Patterns
Measure one import package measure-package
pytest --cov=myapp --cov-report=term-missingA named `--cov` value overrides coverage.py source configuration. Use bare `--cov` to preserve configured sources.
Fail CI below 90 percent fail-threshold
pytest --cov=myapp --cov-fail-under=90Version 7.1.0 fixes the total calculation that could change when a different report combination was selected.
Record branch as well as statement execution measure-branches
pytest --cov=myapp --cov-branch --cov-report=term-missingBranch mode checks decision outcomes and usually reports a lower figure than statement-only measurement.
Write terminal details and an XML artifact write-multiple-reports
pytest --cov=myapp --cov-report=term-missing --cov-report=xml:coverage.xmlRequest `term` or `term-missing` explicitly when adding another report and terminal output is still required.
Start coverage in child Python interpreters configure-subprocesses
# .coveragerc
[run]
patch = subprocess
parallel = truepytest-cov 7 no longer injects automatic subprocess startup. The coverage.py patch setting now controls it.
Merge execution from xdist workers run-with-xdist
pytest -n auto --cov=myapp --cov-report=xmlEvery local or remote worker needs compatible pytest-cov and coverage.py installations.
Associate covered lines with pytest node IDs record-test-contexts
pytest --cov=myapp --cov-context=testParametrized node IDs are stored as contexts and can make the coverage database much larger.
Combine unit and integration runs deliberately append-runs
pytest tests/unit --cov=myapp
pytest tests/integration --cov=myapp --cov-append
coverage reportWithout `--cov-append`, the second command erases coverage left by the first.
Select a nonstandard coverage configuration use-config-file
pytest --cov --cov-config=config/coverage.iniAn explicit path prevents discovery from changing when a worker or child interpreter starts elsewhere.
Build a browsable line-by-line report generate-html
pytest --cov=myapp --cov-report=html:coverage-htmlHTML is convenient for local inspection. CI integrations more often consume XML, JSON, or LCOV.
Exclude generated and migration files omit-generated-code
# .coveragerc
[run]
source = myapp
branch = true
[report]
omit =
*/migrations/*
myapp/generated/*Keep omit rules in the shared coverage configuration so local and CI commands calculate the same denominator.
List uncovered line numbers in the terminal show-missing-lines
pytest --cov --cov-report=term-missing:skip-coveredThe `skip-covered` suffix hides files at 100 percent and keeps the terminal report focused on remaining gaps.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| coverage | PyPI | Use coverage.py directly when pytest does not own the process or plugin behavior is unnecessary. |
| nox | PyPI | Use it to coordinate test and coverage commands across several Python environments. |
| pytest-xdist | PyPI | Use it for parallel pytest execution when a coverage report is not part of the requirement. |
More testing guides
pytest · chai · vitest · jsdom · playwright · coverage · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

