pytest-cov: Coverage Plugin for pytest

raw JSON →
7.1.0 verified Wed Apr 15 auth: no python quickstart: verified

pytest-cov is a pytest plugin that provides comprehensive code coverage functionality, integrating seamlessly with `coverage.py`. It extends pytest with features like automatic erasing and combination of `.coverage` data files, support for detailed coverage contexts, and compatibility with `pytest-xdist` for distributed testing. It is actively maintained by the pytest-dev team.

pip install pytest-cov
error pytest: error: unrecognized arguments: --cov
cause The pytest-cov plugin is not installed in the current Python environment or is not discoverable by pytest.
fix
pip install pytest-cov
error No data to report.
cause pytest-cov was unable to collect any coverage data for the specified target, often because the `--cov` path is incorrect, or the tests do not execute code within that path.
fix
Ensure the path provided to --cov (e.g., pytest --cov=my_package tests/) is correct and that the tests actually execute code within the specified package or module.
error ModuleNotFoundError: No module named 'coverage'
cause The underlying `coverage.py` library, which `pytest-cov` depends on, is not installed in the Python environment.
fix
pip install coverage
breaking Subprocess coverage measurement changed significantly in pytest-cov 7.0.0. Older versions (6.3 and below) relied on a `.pth` file, which was removed. For subprocess coverage, you must now explicitly configure `coverage.py`'s patching options (e.g., `coverage run --rcfile=.coveragerc -m pytest`).
fix Consult `coverage.py` documentation for subprocess configuration. Ensure your `.coveragerc` or `pyproject.toml` correctly specifies `[run] relative_files = true` and `[run] source` paths, and apply appropriate patching.
breaking Support for multiprocessing was dropped in pytest-cov 4.0.0 (released September 28, 2022) due to inherent flakiness and maintenance challenges.
fix Avoid using `pytest-cov` for direct multiprocessing coverage. If parallel execution is needed, `pytest-xdist` is supported, but for `coverage.py` itself across truly separate processes, manual combining of `.coverage` files might be necessary or explore `coverage.py`'s own capabilities.
gotcha Users often encounter 'No data was collected' errors, especially after reorganizing tests into nested subdirectories. This indicates `pytest-cov` couldn't trace your application code.
fix Verify the `--cov` target path is correct and points to your application code's root directory or package. Check your `.coveragerc` or `pyproject.toml` for any exclusions (`[run] omit`, `[report] exclude_lines`) that might be inadvertently blocking files. As a workaround or alternative, consider running tests directly via `coverage run -m pytest`.
gotcha Specific `pytest-cov` versions might be required for compatibility with older Python versions. For example, Python 3.8 typically requires `pytest-cov < 6.0.0`, and Python 3.7 requires `pytest-cov < 5.0.0`.
fix Always install the latest `pytest-cov` version compatible with your project's Python interpreter. Use a `requirements.txt` with version pins or consult the `pytest-cov` documentation/changelog for specific compatibility matrices.
gotcha While `pytest-cov` offers command-line flags for reporting, complex or persistent coverage configurations (e.g., custom inclusions/exclusions, minimum coverage thresholds) are best managed in `coverage.py`'s dedicated configuration file (`.coveragerc` or `pyproject.toml`).
fix Consolidate your coverage configuration in a `.coveragerc` file (or `[tool.coverage]` section in `pyproject.toml`). `pytest-cov` will automatically pick up these settings, providing a cleaner `pytest` command line and more maintainable configuration.

Create a simple Python module (`app.py`) and a test file (`test_app.py`). Run pytest with the `--cov` flag, pointing to the module or directory you want to measure coverage for. This will output a summary to the terminal. You can specify different report formats like HTML, XML, or JSON using `--cov-report`.

import pytest

# app.py
def greet(name):
    if name:
        return f"Hello, {name}!"
    return "Hello, World!"

# test_app.py
def test_greet_with_name():
    assert greet("Alice") == "Hello, Alice!"

def test_greet_without_name():
    assert greet(None) == "Hello, World!"

# To run this, save as app.py and test_app.py, then:
# pytest --cov=app test_app.py
# You'll see a coverage report in your terminal.
# For an HTML report: pytest --cov=app --cov-report=html test_app.py