pytest-cov runs coverage inside pytest and owns the data file
Coverage plugin for pytest.
At a glance
- What is it?
- pytest-cov wraps the coverage package in a pytest plugin so the data file is erased, combined and reported without extra commands. Its sharp edges are subprocess measurement, which moved out of a .pth file in version 7, and xdist workers that have to carry their own install.
- Who is it for?
- Adopt pytest-cov for a pytest suite that wants coverage in one command, and above all when xdist workers are involved, but check first that your coverage config carries the patch settings that replaced the old .pth file. Leave it out when your suite relies on the working directory being importable, or when you cannot install the package on every worker in a container image or CI matrix.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Star history
- pytest-dev/pytest-cov2,068 ★ · +0
| Repository | 2026-10-14 | 2026-10-23 |
|---|---|---|
| pytest-dev/pytest-cov | 2.1k | 2.1k |
0 Stars in the last 9 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A pytest11 entry point puts coverage inside the pytest process
pytest-cov measures nothing on its own. It drives the coverage package and removes the friction that appears when a test runner has to live inside another tool. The comparison the project draws is `coverage run -m pytest` against `pytest --cov`, and the difference shows up at import time: the `coverage run` route puts the current directory on `sys.path`, while running `pytest` directly does not, so a module that only imports because of the working directory can behave differently and skew the report before a single assertion runs.
The hook is a pytest11 entry point declared in pyproject.toml, so the plugin loads whenever pytest starts, with no conftest edit and no extra flag.
[project.entry-points.pytest11]
pytest_cov = "pytest_cov.plugin"Two conveniences follow from that registration. Reports appear without being asked for, and data files are handled for you across processes. Everything the coverage package offers stays reachable, either through pytest-cov's own command line options or through coverage's config file, so nothing in the underlying tool is locked away.
The data file is erased before the run and left afterwards
Every session begins by deleting the data file, and the file is left in place at the end so ordinary coverage tools can examine the result. That lifecycle explains most surprises in the totals. A `.coverage` file from yesterday is not merged into today's number, so a stale report or a narrower selector never quietly inflates the result.
To accumulate figures across sessions, add `--cov-append`, which appends the new data to coverage data from previous test runs.
There is a tension inside the project's own text here. The summary advertises automatic erasing and combination of `.coverage` files as an extra over `coverage run`, yet the data file section states plainly that the file is erased at the start and that combining several runs means choosing `--cov-append`. Read those two parts together and combination is opt-in for repeated local sessions, not automatic; what the plugin combines on its own is the parallel case, which is also why the xdist workers hand their data back to one place.
Subprocess measurement moved out of a .pth file in version 7
Before this change, coverage in subprocesses was switched on by a `.pth` file placed in site-packages. pytest-cov 6.3 and older relied on it, and version 7 removed the mechanism entirely, handing the job to coverage's own patch options.
For an existing suite the consequence is concrete. After the bump, any child process that used to be measured stops being measured unless the coverage configuration enables the patch behaviour, and the percentage drops with no test change and no error message. The same loss applies to custom runners that relied on the file being imported for them.
The project does not document a compatibility switch that restores the old file. The fix lives in coverage's config file, on the patch settings the project links to, which means the upgrade touches configuration as well as dependencies.
Uninstalling can strand a .pth file in site-packages
Removal is a single pip command, with one leftover risk the project calls out directly: a stray `.pth` file may remain in site-packages after the package is gone. Which name to look for depends on how old the install was.
pip uninstall pytest-covAn install from `pytest-cov 2.0` may leave a `pytest-cov.pth` behind, specifically when the package was installed without a wheel, through `easy_install` or `setup.py install`. An install from `pytest-cov 1.8 or older` leaves a different file, named `init_cov_core.pth`. Anyone moving from a long-lived environment to a fresh one should look in that directory before blaming the numbers, because the leftover file belongs to an install that no longer exists yet can still be picked up.
Xdist workers must install the plugin themselves
Distributed testing carries a hard constraint. Workers must have the pytest-cov package installed, and the reason given is plugin registration: the plugin has to be registered through setuptools for pytest to start it on the worker, so a worker without the package never starts it.
pip install pytest-xdistThe same rule covers remote interpreters, which the project lists as supported, with all of pytest-xdist's features and coverage still collected. In practice that shapes container images and CI matrices, where test dependencies are often installed separately from the package under test. A worker environment missing the plugin does not fail loudly; coverage simply comes back empty, and the report you get is a table of zeroes that looks like a real result.
One install and one command produce the table
Start with the package itself, then point the run at the package you want measured.
pip install pytest-covpytest --cov=myproj tests/The table that follows names each module with its statement count, misses and percentage. In the sample output, `myproj/myproj` carries 257 statements with 13 missed at 94%, `feature4286` shows 94 statements with 7 missed at 92%, and the TOTAL line reads 353 statements, 20 missed, 94%. The data file survives the run, so the same numbers can be re-examined with coverage's own reporting afterwards. If you need to know which test touched which line, `--cov-context=test` records the full test name, parametrization included, as the coverage context.
Dependencies sit higher than a plain coverage install would
pyproject.toml states the floor precisely. Runtime dependencies are `coverage[toml]>=7.10.6`, `pytest>=7` and `pluggy>=1.2`, and `requires-python` is >=3.9, so an interpreter older than that cannot take the plugin. Classifiers cover Python 3.9 through 3.14 on both CPython and PyPy, and the build uses hatchling with hatch-fancy-pypi-readme. An optional `testing` group adds process-tests, pytest-xdist and virtualenv, which is what the project's own suite runs on.
dependencies = [
"coverage[toml]>=7.10.6",
"pytest>=7",
"pluggy>=1.2",
]The package is MIT licensed and the last push was on 2026-09-21. The declared version in pyproject.toml is 7.1.0, and the version badge in the README points at the same tag, so the manifest and the README agree on where the code stands rather than drifting apart.
When coverage run -m pytest is the better route
The older invocation is still a legitimate choice, and the difference is mechanical rather than cosmetic. `coverage run -m pytest` leaves the working directory on `sys.path` and pytest-cov does not, which flips the behaviour for any module that relies on that import path. It also leaves data file handling to coverage's own defaults instead of erasing at startup and printing a report per run. Neither `--cov-context=test` nor xdist's remote interpreters have an equivalent there.
What the two share is coverage's config file, since everything the coverage package offers works through it. The deciding factor is therefore the test runner, not the measurement: a suite that measures coverage outside pytest, or whose import rules depend on the working directory, gets more predictable results from the plain route, while a pytest suite running distributed workers gets its manual steps removed by the plugin.
Editorial conclusion
Adopt pytest-cov for a pytest suite that wants coverage in one command, and above all when xdist workers are involved, but check first that your coverage config carries the patch settings that replaced the old .pth file. Leave it out when your suite relies on the working directory being importable, or when you cannot install the package on every worker in a container image or CI matrix. The first check after an upgrade from 6.3 is whether subprocess lines still show up in the report, because the missing measurement looks like a coverage drop rather than a config gap.
Frequently asked questions
Does pytest-cov work with pytest-xdist?
Yes, xdist support is one of the extras the project lists, including remote interpreters, with coverage still collected. The workers must have the pytest-cov package installed themselves, because the plugin has to be registered through setuptools for pytest to start it on a worker.
How do I keep coverage data from earlier test runs?
Add the `--cov-append` option. Without it the data file is erased at the beginning of testing, so results from previous runs are not merged into the new report.
What changed about subprocess coverage in pytest-cov 7?
pytest-cov 6.3 and older used a `.pth` file to enable coverage measurements in subprocesses, and that was removed in pytest-cov 7. Subprocess measurement now has to be enabled through coverage's patch options in coverage's config file.
Which Python versions and packages does pytest-cov need?
pyproject.toml sets `requires-python` to >=3.9, with classifiers for Python 3.9 through 3.14 on CPython and PyPy. Runtime dependencies are `coverage[toml]>=7.10.6`, `pytest>=7` and `pluggy>=1.2`.
How do I remove pytest-cov cleanly?
Run `pip uninstall pytest-cov`. A stray `.pth` file may remain in site-packages: pytest-cov 2.0 can leave a `pytest-cov.pth` when installed without a wheel, and pytest-cov 1.8 or older leaves an `init_cov_core.pth`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pytest-dev-pytest-cov)Star history chart for your README
[](https://hysenlabs.com/projects/pytest-dev-pytest-cov)Was this useful?