Learning Goals
3 min- Run coverage through pytest with
--cov. - Generate and browse an HTML coverage report.
- Fail the run under a threshold with
--cov-fail-under. - Configure it once in
pyproject.toml.
Warm-Up · One Command
5 minpip install pytest-cov pytest --cov=myapp # run tests + show coverage for the myapp package
Instead of two commands (coverage run then coverage report), pytest-cov does it in one: pytest --cov=pkg. Add an HTML report to see exactly which lines are red, and a threshold so the build fails if coverage slips.
New Concept · --cov & Reports
14 minTerminal report (with missing lines)
$ pytest --cov=myapp --cov-report=term-missing ... Name Stmts Miss Cover Missing --------------------------------------------------- myapp/cart.py 20 0 100% myapp/grades.py 6 2 67% 2, 6 --------------------------------------------------- TOTAL 26 2 92%
HTML report — click through your code
$ pytest --cov=myapp --cov-report=html # creates htmlcov/index.html # open it: covered lines green, missed lines RED, line-by-line
The HTML view is the best way to find gaps — red lines jump out, and you click into each file to see exactly what wasn't run.
Branch coverage too
pytest --cov=myapp --cov-branch --cov-report=term-missing # Missing now shows things like "8->10" (a branch from line 8 to 10 not taken)
Fail the build under a threshold
pytest --cov=myapp --cov-fail-under=80 # exits non-zero (build FAILS) if total coverage < 80%
This is how teams keep coverage from rotting — a PR that drops coverage below the bar can't merge (CI, Lesson 46).
Configure once in pyproject.toml
[tool.pytest.ini_options] addopts = "--cov=myapp --cov-branch --cov-report=term-missing --cov-fail-under=80" [tool.coverage.run] omit = ["*/tests/*", "*/__init__.py"] # don't measure test files themselves
Now a bare pytest runs everything with coverage, branch tracking, and the threshold — no flags to remember.
Worked Example · A Coverage-Gated Project
12 minshop/ ├─ shop/ │ ├─ __init__.py │ ├─ cart.py │ └─ pricing.py ├─ tests/ │ ├─ test_cart.py │ └─ test_pricing.py └─ pyproject.toml
# pyproject.toml [tool.pytest.ini_options] testpaths = ["tests"] addopts = """ --cov=shop --cov-branch --cov-report=term-missing --cov-report=html --cov-fail-under=85 """ [tool.coverage.run] omit = ["*/tests/*", "*/__init__.py"]
$ pytest ... Name Stmts Miss Cover Missing ----------------------------------------------------- shop/cart.py 20 0 100% shop/pricing.py 12 1 92% 18 ----------------------------------------------------- TOTAL 32 1 97% Required test coverage of 85% reached. Total: 97% ======================== 14 passed in 0.06s ========================= # htmlcov/index.html written — open to see line 18 in red
Read the diff
One pytest command now: runs tests, measures branch coverage, prints missing lines, writes an HTML report, and enforces an 85% floor. The team gets fast feedback AND a guardrail — if someone's PR drops coverage below 85%, the run fails. The HTML report turns "line 18" into a clickable red line you can immediately go test.
Try It Yourself
13 minRun pytest --cov=yourpkg --cov-report=term-missing on a project. Read the per-file breakdown.
Generate the HTML report and open htmlcov/index.html. Click into the lowest-coverage file and find the red lines.
Add the full pyproject.toml config with --cov-fail-under. Set the threshold just above your current coverage and confirm the run fails; add a test to pass it.
Mini-Challenge · Coverage Diff
8 minRecord your project's current coverage. Add a new feature (a function) WITHOUT tests — watch coverage drop and the --cov-fail-under gate fail. Then write tests to bring it back above the bar. This is the real PR workflow.
Recap
3 minpytest --cov=pkg measures coverage during the test run. Add --cov-report=html for a clickable, colour-coded report, --cov-branch for branch coverage, and --cov-fail-under=N to fail the build below a threshold. Configure it all in pyproject.toml. The HTML report + a gate is the professional setup. Next: how much coverage is actually enough.
Vocabulary Card
- pytest-cov
- A pytest plugin that runs coverage as part of the test command.
- --cov-report=html
- Generates a browsable, colour-coded coverage report.
- --cov-fail-under
- Fails the test run if total coverage is below a threshold.
- omit
- Coverage config to exclude files (like tests themselves) from measurement.
Homework
4 minSet up pytest-cov on a real project with a pyproject.toml config: branch coverage, term-missing + HTML reports, and a --cov-fail-under threshold. Submit a screenshot of the HTML report and the config. Get the project above your chosen bar.
Use the shop/ pyproject.toml as the template, swapping in your package name. The HTML report lives in htmlcov/.