Code coverage measures which lines of your source code are executed during tests. A high coverage percentage doesn't guarantee correctness, but a low one reveals untested paths.
pytest-cov
pip install pytest-covRun tests with coverage:
pytest --cov=myapp tests/Generate an HTML report:
pytest --cov=myapp --cov-report=html tests/
# open htmlcov/index.htmlOutput:
---------- coverage: platform linux ----------
Name Stmts Miss Cover
-----------------------------------------
myapp/auth.py 42 3 93%
myapp/models.py 61 8 87%
myapp/utils.py 28 0 100%
-----------------------------------------
TOTAL 131 11 92%Fail Below a Threshold
pytest --cov=myapp --cov-fail-under=80 tests/The command exits with a non-zero code if coverage drops below 80% — CI picks this up as a failure.
.coveragerc Configuration
# .coveragerc
[run]
source = myapp
omit =
myapp/migrations/*
myapp/tests/*
*/conftest.py
[report]
fail_under = 80
show_missing = trueOr in pyproject.toml:
[tool.coverage.run]
source = ["myapp"]
omit = ["myapp/migrations/*"]
[tool.coverage.report]
fail_under = 80
show_missing = trueGitHub Actions Workflow
# .github/workflows/pytest.yml
name: Pytest
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install pytest pytest-cov pytest-mock
- name: Run tests with coverage
run: pytest --cov=myapp --cov-report=xml --cov-fail-under=80
- name: Upload coverage report
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: htmlcov/
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
file: coverage.xmlCoverage Report Visualiser
Coverage report simulation
Ctrl+Enter
HTML
CSS
JS
Preview
Useful pytest Flags Summary
pytest -v # verbose — show test names
pytest -s # show print() output
pytest -x # stop on first failure
pytest --tb=short # shorter tracebacks
pytest --lf # rerun last failed tests only
pytest -n auto # parallel (requires pytest-xdist)
pytest --cov=myapp --cov-fail-under=80pyproject.toml One-stop Config
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-v --tb=short --cov=myapp --cov-fail-under=80"With this in place, just running pytest applies all your standard flags.