Measure which code your tests run · the Python coverage tool · verified against coverage.py 7.15

coverage.py cheat sheet

coverage.py measures which lines (and branches) of your code actually run — usually while your tests execute. The loop is simple: run under coverage to gather data, then report it (terminal, HTML, or XML for CI). Add branch coverage to catch untested if/else paths, set a fail_under threshold to gate merges, and configure it all from pyproject.toml. This sheet targets coverage.py 7.15 (Python 3.10–3.15).

run reports config & gate exclude integrate & scale gotcha most common

Verified 2026-08-25 against the official docs at coverage.readthedocs.io (coverage.py 7.15.4, 2026-08-06; Python 3.10–3.15, incl. free-threading). Data lives in a .coverage SQLite file. pytest-cov wraps this same engine for pytest users.

Outline

coverage run -m pytest gathers data → coverage report -m / coverage html shows it. Turn on --branch, configure via [tool.coverage], exclude what shouldn't count, and gate CI with fail_under.

Measure

  1. 1 · Install & run
  2. 2 · Reports
  3. 3 · Branch coverage

Configure

  1. 4 · Config (pyproject)
  2. 5 · Exclude & omit
  3. 6 · fail_under & CI

Integrate & scale

  1. 7 · pytest-cov
  2. 8 · Parallel & contexts
  3. 9 · Gotchas
  4. Worth memorizing

Measure

Run your tests under coverage, then read the results.

1Install & run7.15
2Reportsterminal, HTML, XML
3Branch coveragebeyond lines

Configure

Put settings in one place, exclude noise, and enforce a threshold.

4Config (pyproject)one source of truth
5Exclude & omitwhat shouldn't count
6fail_under & CIenforce a threshold

Integrate & scale

Use it through pytest, and handle parallel / subprocess runs.

7pytest-covthe pytest front-end
8Parallel & contextscombine + who-tested-what
!Common gotchasread before shipping

Worth memorizing

coverage run -m pytestreplace python with coverage run
--source=mypkgmeasure your code, not the world
coverage report -mtable + missing line numbers
coverage html -> htmlcov/clickable annotated source
coverage xmlCobertura for CI / Codecov
--branch / branch = truecatch untested if/else paths
[tool.coverage.*] in pyprojectsource, branch, omit, report
# pragma: no coverexclude a line/block
exclude_also = [...] regexesTYPE_CHECKING, NotImplementedError, __main__
fail_under = 90non-zero exit gates CI
parallel=true -> coverage combinemerge before report
pytest --cov=pkg --cov-report=term-missingsame engine via pytest-cov