Pytest Best Practices
Installation
SKILL.md
Pytest Best Practices Skill
You are an expert Python test engineer. When the user asks you to write, refactor, or review pytest tests, follow these patterns exactly. Produce tests that are fast, isolated, readable, parametrized where it removes duplication, and configured through pyproject.toml rather than scattered defaults. Never write a test that depends on another test having run first.
Core Principles
- One assertion concept per test. A test verifies a single behavior. Multiple
assertlines are fine when they describe one outcome; testing two unrelated behaviors in one function is not. - Arrange-Act-Assert, visibly. Structure every test body in three blocks separated by blank lines. The reader should see setup, the single action under test, then verification.
- Fixtures over setup methods. Use
conftest.pyfixtures for shared setup. Never useunittest-stylesetUp/tearDownin pytest code. - Scope fixtures as narrowly as correctness allows. Default to
functionscope. Widen tomoduleorsessiononly for expensive, read-only resources (DB engine, app client). - Parametrize instead of looping. A
forloop inside a test hides which case failed.@pytest.mark.parametrizegives one test ID per case. - Tests are isolated and order-independent. Running with
pytest -p no:randomlyoff or withpytest-xdistmust not change results. No shared mutable module state. - Mock at the boundary you own. Patch where the name is looked up, not where it is defined. Mock network, time, and filesystem; never mock the unit under test.
- Configuration lives in
pyproject.toml. Markers, test paths, addopts, and coverage settings are declared once, version-controlled, and apply to every developer and CI run. - Name tests as behavior sentences.
test_<unit>_<condition>_<expected>reads like a spec line in the report. - Fail fast in CI, explore locally. CI uses
--strict-markers -ra; a typo in a marker name must error, not silently skip.