Test observable behavior and contracts, not internal implementation.
Keep unit tests fast, deterministic, and patched at module boundaries.
These are preferred defaults for common cases.
When a default conflicts with project constraints, suggest a better-fit alternative, call out tradeoffs, and note compensating controls.
Invocation Notice
Inform the user when this skill is being invoked by name: python-testing.
When to Use
Writing or reviewing unit, integration, or reliability-sensitive tests.
Tests are flaky, slow, or coupled to implementation details.
Adding regression tests after a bugfix.
Testing async lifecycles, cancellation, or cleanup paths.
Unsure what test coverage a change needs.
Testing across multiple Python versions (nox, CI matrix).
Validating thread safety for free-threaded Python (GIL-disabled builds).
When NOT to use:
Pure data-shape or schema validation (see python-types-contracts).
Production observability or monitoring concerns (see python-runtime-operations).
Concurrency design decisions outside of test harnesses (see python-concurrency-performance).
Quick Reference
Test observable behavior, not internals.
Keep unit tests fast and deterministic.
Patch at module boundaries and import locations used by the unit under test.
Add regression tests for bugfixes.
Include timeout/retry/cancellation/cleanup coverage where relevant.
For multi-Python: use nox with uv backend; parametrize for dependency matrices.
For free-threaded Python: use pytest-run-parallel, set PYTHON_GIL=0, always set CI timeouts.
Change-Specific Diagnostics
Dependency updates: run uv run pytest scripts/test_pypi_security_audit.py -v
Async-heavy lifecycle changes: run pyleak diagnostics.
Multi-Python support changes: run full matrix via nox.
Free-threaded compatibility: run PYTHON_GIL=0 uv run --python 3.Xt pytest --parallel-threads=auto --timeout=300 on a free-threaded build (3.13t+).
Common Mistakes
Mocking too deep — patching internals instead of module-boundary seams makes tests brittle and coupled to implementation.
Testing the mock — verifying mock call counts without asserting on observable output proves nothing about behavior.
Missing regression test — fixing a bug without a test that reproduces it first; the bug will recur.
Non-deterministic time/order — relying on wall-clock time or dict/set ordering instead of injecting clocks and sorting explicitly.
Skipping cleanup assertions — verifying the happy path but never asserting that resources are released on failure or cancellation.
No free-threaded CI entry — shipping multi-threaded code without a free-threaded (t-suffixed) matrix entry; the GIL hides race conditions that will surface when free-threaded Python becomes the default.
Ignoring GIL re-enablement — importing a C extension without Py_mod_gil silently re-enables the GIL; check sys._is_gil_enabled() after imports.
YAML version float — writing 3.10 unquoted in CI matrix YAML; it parses as 3.1 and installs the wrong Python.
References
references/testing-strategy.md
references/pytest-practices.md
references/async-and-concurrency-testing.md
references/reliability-lifecycle-testing.md
references/multi-python-testing.md
references/free-threaded-testing.md
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: ahgraber-skills-python-testing3description: Python Testing4---56# Python Testing78## Overview910Test observable behavior and contracts, not internal implementation.11Keep unit tests fast, deterministic, and patched at module boundaries.1213These are preferred defaults for common cases.14When a default conflicts with project constraints, suggest a better-fit alternative, call out tradeoffs, and note compensating controls.1516## Invocation Notice1718- Inform the user when this skill is being invoked by name: `python-testing`.1920## When to Use2122- Writing or reviewing unit, integration, or reliability-sensitive tests.23- Tests are flaky, slow, or coupled to implementation details.24- Adding regression tests after a bugfix.25- Testing async lifecycles, cancellation, or cleanup paths.26- Unsure what test coverage a change needs.27- Testing across multiple Python versions (nox, CI matrix).28- Validating thread safety for free-threaded Python (GIL-disabled builds).2930**When NOT to use:**3132- Pure data-shape or schema validation (see `python-types-contracts`).33- Production observability or monitoring concerns (see `python-runtime-operations`).34- Concurrency design decisions outside of test harnesses (see `python-concurrency-performance`).3536## Quick Reference3738- Test observable behavior, not internals.39- Keep unit tests fast and deterministic.40- Patch at module boundaries and import locations used by the unit under test.41- Add regression tests for bugfixes.42- Include timeout/retry/cancellation/cleanup coverage where relevant.43- For multi-Python: use nox with uv backend; parametrize for dependency matrices.44- For free-threaded Python: use `pytest-run-parallel`, set `PYTHON_GIL=0`, always set CI timeouts.4546## Change-Specific Diagnostics4748- Dependency updates: run `uv run pytest scripts/test_pypi_security_audit.py -v`49- Async-heavy lifecycle changes: run `pyleak` diagnostics.50- Multi-Python support changes: run full matrix via `nox`.51- Free-threaded compatibility: run `PYTHON_GIL=0 uv run --python 3.Xt pytest --parallel-threads=auto --timeout=300` on a free-threaded build (3.13t+).5253## Common Mistakes5455- **Mocking too deep** — patching internals instead of module-boundary seams makes tests brittle and coupled to implementation.56- **Testing the mock** — verifying mock call counts without asserting on observable output proves nothing about behavior.57- **Missing regression test** — fixing a bug without a test that reproduces it first; the bug will recur.58- **Non-deterministic time/order** — relying on wall-clock time or dict/set ordering instead of injecting clocks and sorting explicitly.59- **Skipping cleanup assertions** — verifying the happy path but never asserting that resources are released on failure or cancellation.60- **No free-threaded CI entry** — shipping multi-threaded code without a free-threaded (`t`-suffixed) matrix entry; the GIL hides race conditions that will surface when free-threaded Python becomes the default.61- **Ignoring GIL re-enablement** — importing a C extension without `Py_mod_gil` silently re-enables the GIL; check `sys._is_gil_enabled()` after imports.62- **YAML version float** — writing `3.10` unquoted in CI matrix YAML; it parses as `3.1` and installs the wrong Python.6364## References6566- `references/testing-strategy.md`67- `references/pytest-practices.md`68- `references/async-and-concurrency-testing.md`69- `references/reliability-lifecycle-testing.md`70- `references/multi-python-testing.md`71- `references/free-threaded-testing.md`7273---74> Converted and distributed by [TomeVault](https://tomevault.io/claim/ahgraber) — claim your Tome and manage your conversions.75<!-- tomevault:4.0:skill_md:2026-04-11 -->
Run npx skillmds@latest add tomevault-io/ahgraber-skills-python-testing in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Python Testing It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
tomevault-io (@tomevault-io) published this skill. Their other Agent Skills are listed on their SkillMD profile.