Testing Best Practices
Rules for a pytest suite that is fast, reliable, and maintainable.
Search across all documentation pages
Rules for a pytest suite that is fast, reliable, and maintainable.
test_discount_over_100_raises, not test_discount_3.@pytest.mark.slow excluded from default CI run.conftest.py for reuse.user_factory(email="...") over static dicts.src/ only. 80% floor; higher for auth and billing modules.branch = true in coverage config.requires-python bounds with nox or CI matrix.@pytest.mark.flaky only as temporary measure.tests/unit/ and tests/integration/ directories.Full unit suite under 60 seconds. Individual tests under 100ms.
Roughly 80/20. Most tests unit; integration covers critical paths.
Test through public API. Private helpers are covered indirectly.
tests/fixtures/data/ with path via pathlib.Path(__file__).parent.
Useful for serializers and templates. Review snapshot updates carefully in PRs.
One logical behavior. Multiple asserts ok if they verify one outcome.
Unit: no. Integration/staging: yes against test environment.
caplog fixture: with caplog.at_level(logging.ERROR):.
pytest-xdist -n auto for large suites. Ensure test isolation first.
@pytest.mark.skip with reason for platform-specific or unfinished work. Not for failing tests.
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026