Files
prompts/docs/skills/pytesting/SKILL.md
T
2026-06-21 22:55:58 -05:00

138 lines
7.6 KiB
Markdown

---
name: pytesting
description: "Reference hub for pytest suite structure, naming, markers, and stack-specific testing patterns. Optimized for progressive discovery so naming and hierarchy guidance are loaded first when shaping or reorganizing tests."
x-personal-mcp:
id: pytesting
version: 1.0.0
tags:
- pytest
- testing
- python
- fastapi
- asyncio
- anyio
- deterministic
capabilities:
- resource://skills/pytesting/document
---
# Pytest Scaffolding
This skill is a collection of best-practice references and source-documentation links for building and maintaining pytest suites.
Use it to quickly find the right guidance for:
1. Baseline pytest structure and marker strategy.
2. Naming conventions and test hierarchy organization.
3. FastAPI route, dependency override, and lifespan testing patterns.
4. SQLAlchemy transaction and session testing patterns.
5. AsyncIO loop-scope, fixture-lifecycle, and cancellation-safe testing patterns.
Repository defaults:
- `uv run pytest` is the canonical invocation.
- pytest settings live in `pyproject.toml` under `[tool.pytest.ini_options]`.
- strict marker checking is expected (`--strict-markers`).
## Progressive Discovery Start
Use this load order by default so guidance stays targeted and naming conventions are pulled in early:
1. Classify intent first: naming and organization, baseline pytest mechanics, FastAPI testing, SQLAlchemy testing, or mixed.
2. For create/restructure/rename tasks, load [naming-and-organization.md](./references/naming-and-organization.md) first.
3. Load [pytest-docs.md](./references/pytest-docs.md) next for fixture and marker defaults.
4. Load at most one stack-specific reference unless the request is explicitly mixed stack.
5. If confidence is low after two references, ask one clarifying question before loading more.
Load budget defaults:
1. Single-stack task: 1 to 2 references.
2. Mixed-stack task: up to 3 references.
3. Avoid loading all references unless the user explicitly asks for a broad audit.
## Intent Router
Open only the reference that matches the immediate task.
1. Naming, file layout, discovery prefixes, class/function naming: [naming-and-organization.md](./references/naming-and-organization.md)
2. Fixture layering, marker policy, collect-only and fast-path commands: [pytest-docs.md](./references/pytest-docs.md)
3. Route tests, dependency overrides, lifespan handling: [fastapi-testing.md](./references/fastapi-testing.md)
4. Session and transaction fixtures, async ORM behavior: [sqlalchemy-testing.md](./references/sqlalchemy-testing.md)
5. Async test mode selection, event loop scope, cancel-scope teardown issues: [asyncio-testing.md](./references/asyncio-testing.md)
## Naming Pull-In Triggers
Always consult [naming-and-organization.md](./references/naming-and-organization.md) before recommending structure when any of these are true:
1. New tests are being added.
2. Existing tests are being reorganized or renamed.
3. The request mentions conventions, readability, hierarchy, or discoverability.
4. The task introduces parametrization where case naming affects failure readability.
## Baseline Best Practices
These are stable defaults regardless of stack:
1. Apply pytest naming and hierarchy conventions first so discovery and ownership stay predictable; see [naming-and-organization.md](./references/naming-and-organization.md).
2. Mirror `src/` into `tests/` so ownership and coverage are obvious.
3. Keep fixtures explicit and layered (`tests/conftest.py` globally, subtree `conftest.py` for domain-specific fixtures).
4. Register markers up front (`unit`, `integration`, `smoke`, `slow`, `external`) and keep strict marker checks enabled.
5. Separate fast feedback (`-m unit`) from broader integration/external lanes.
6. Validate structure early with collection checks before expanding assertions.
7. Keep test scope tight and count intentional; add tests only when each case protects a distinct behavior.
8. Start with the single core-intent behavior path, then add edge cases based on real risk.
9. Prefer parametrized tests for behavior variants instead of cloning near-identical test functions.
10. Reject low-signal assertions (for example `assert True` patterns) and avoid tests that only assert a mock was called.
11. Prefer behavior-first tests that exercise real code paths and concrete inputs over patching internals.
12. Use monkeypatching, mocks, and fakes extremely sparingly, only when no practical real-input alternative exists, and only after explicit user confirmation.
## Universal Test Double Policy (Repo-Local Placement)
Treat this policy as universal guidance for test authoring, while it is documented in this repository-local skill file for now.
Apply this policy whenever a test change introduces a fake collaborator or patched behavior:
1. Attempt a real-input, real-object test design first.
2. If that approach is impractical, explain why and request user confirmation before adding monkeypatching, mocks, or fakes.
3. Keep any approved test double narrowly scoped and document the exact boundary it replaces.
4. Do not treat call-only verification as sufficient; pair any test double with assertions on observable behavior or outputs.
5. Revisit approved test doubles when implementation seams improve so they can be removed.
## Stack-Specific Guidance
- For FastAPI, prefer dependency overrides and clear lifecycle handling; see [fastapi-testing.md](./references/fastapi-testing.md).
- For SQLAlchemy, prefer transaction-safe session fixtures and explicit async loading strategy; see [sqlalchemy-testing.md](./references/sqlalchemy-testing.md).
- For async fixtures, loop-scope selection, and cancellation-safe teardown, see [asyncio-testing.md](./references/asyncio-testing.md).
- For naming and tree organization, use the conventions in [naming-and-organization.md](./references/naming-and-organization.md).
## Source Documentation Entry Points
Primary upstream docs are curated in each reference page. Start with:
1. Pytest good practices: [pytest docs](https://docs.pytest.org/en/stable/explanation/goodpractices.html)
2. Pytest fixtures: [fixture how-to](https://docs.pytest.org/en/stable/how-to/fixtures.html)
3. Pytest markers: [marker examples](https://docs.pytest.org/en/stable/example/markers.html)
4. FastAPI testing: [FastAPI testing tutorial](https://fastapi.tiangolo.com/tutorial/testing/)
5. SQLAlchemy transaction testing: [SQLAlchemy external transaction pattern](https://docs.sqlalchemy.org/en/20/orm/session_transaction.html#joining-a-session-into-an-external-transaction-such-as-for-test-suites)
6. Pytest monkeypatch usage and limits: [monkeypatch how-to](https://docs.pytest.org/en/stable/how-to/monkeypatch.html)
7. pytest-asyncio configuration: [pytest-asyncio config](https://pytest-asyncio.readthedocs.io/en/stable/reference/configuration.html)
8. AnyIO cancellation semantics: [AnyIO cancellation and timeouts](https://anyio.readthedocs.io/en/stable/cancellation.html)
## Quick Validation Commands
Use these commands to check structure and execution lanes:
1. `uv run pytest --collect-only -q`
2. `uv run pytest -m unit -q`
3. `uv run pytest -m "not external" -q`
4. `uv run pytest -q`
## Output Contract
When this skill is applied, return:
1. Which references were consulted.
2. The discovery path used (intent classification, load order, and why).
3. Recommended structure, naming, fixture, and marker decisions.
4. Concrete naming outcomes: file/module naming pattern, class usage decision, and any parametrization `ids` conventions.
5. Exact validation commands.
6. Relevant source-doc links for any non-trivial recommendation.
7. Risks, assumptions, or open questions.
8. Explicit confirmation status if monkeypatching, mocks, or fakes were requested or used.