Python Testing
High-signal guidance for writing tests that are deterministic, readable, and maintainable.
When to activate
- Adding tests (unit/integration) for new or existing code
- Refactoring tests to reduce flakiness
- Designing fixtures and test organization
- Adding coverage, CI checks, or async tests
- Property tests (Hypothesis) or concurrent/free-threaded suites
Outcome expectations
- Tests are deterministic and pass reliably in CI.
- Coverage is meaningful; assertions test behavior, not implementation details.
- Flaky tests are rare and quickly diagnosed (fixtures, mocking, timing).
- New developers can understand test intent within 30 seconds of reading.
Recommended triage workflow
For new code:
- Write a failing test (red).
- Implement minimal code to pass (green).
- Refactor with tests staying green.
For flaky/failing tests:
- Check for shared state (mocks, fixtures, filesystem).
- Check for timing assumptions (avoid
sleep, use synchronization). - Check mock patch targets (patch as used, not where defined).
- Isolate to minimal reproduction in separate test.
Core rules
- Prefer small unit tests for logic; use integration tests for boundaries.
- Use pytest fixtures to remove duplication, but avoid fixture overengineering.
- Avoid sleeping in tests; synchronize via conditions/events.
- Mock at boundaries (network, time, DB), not everywhere.
- Coverage is a signal: aim for meaningful assertions, not line-hits.
- Do not add production hooks solely for tests; use real seams or dependency injection.
- Pair with
test-driven-developmentwhen implementing persistent code or bug fixes test-first. - If mocks, timing, or flakes dominate, pair with
testing-reliability; if the root cause is unclear, pair withsystematic-debugging. - Asyncio-heavy tests: also load
python-async-patternstesting.md. CancelledErrorandExceptionGroupare not caught bypytest.raises(Exception)/pytest.raises(ValueError)respectively.
Resources
Load on demand:
references/tdd-and-structure.md— TDD loop, naming, organizing testsreferences/fixtures-parametrize.md— fixtures (scopes, autouse), parametrization patternsreferences/mocking.md— unittest.mock, patching correctly, async mocksreferences/async.md— pytest-asyncio loop scope; cancellation/ExceptionGrouppointersreferences/concurrency.md— load for threads,InterpreterPoolExecutor, free-threaded suitesreferences/property.md— load when example tests miss a space Hypothesis can shrinkreferences/coverage-ci.md— pytest-cov, coverage hygiene, CI tipsreferences/commands.md— common pytest commands and selectors