Python Testing Workflow
Purpose
Make Python tests describe behavior, run through uv, and give a focused
failure signal. Preserve the repository's existing test framework and markers;
use the repository's own checked-in commands for setup and execution.
Workflow
- Inspect
pyproject.toml, existing tests, CI, markers, fixtures, package
layout, and workspace members before changing test configuration.
- Choose the smallest useful test boundary:
- unit tests for pure behavior and fakeable dependencies;
- integration tests for framework, database, filesystem, network, or
process boundaries;
- a client test for public HTTP or MCP behavior;
- a package-artifact smoke test when package contents changed.
- Run a focused check first:
uv run pytest tests/unit
uv run pytest -k "auth and not slow"
uv run --package <member-name> pytest
- Add fixtures for reusable setup, keep their scope minimal, and use
@pytest.mark.parametrize for input/output matrices.
- Use
monkeypatch, dependency overrides, fakes, or disposable services at
the boundary rather than mutating committed configuration or calling a live
dependency during every test.
- Use async tests only when the code under test is async. Configure the
repository's async test support explicitly and verify lifespan behavior when
the app owns startup or shutdown resources.
- Run the relevant complete test selection, then the project's CI-equivalent
validation commands. Add coverage only when the user or repository has a
concrete coverage threshold or reporting need.
FastAPI And FastMCP Boundaries
For FastAPI, override external dependencies with
app.dependency_overrides, reset them after the test, and use an async client
when the test itself needs async behavior. Ensure lifespan events run when the
application depends on them.
For FastMCP, prefer an in-memory Client(mcp) test for deterministic server
behavior, then add transport or authorization integration tests only for the
configured deployment shape. Test listed and callable tools, readable
resources, and rendered prompts separately when each surface is public.
Failure Triage
Classify the first failure before changing code:
- collection or import failure: package layout, test path, missing dependency,
or environment;
- fixture or marker failure: configuration, scope, registration, or setup;
- async/lifespan failure: event-loop ownership, startup, shutdown, or client
configuration;
- assertion failure: behavior, test data, or an intentionally changed public
contract;
- integration failure: isolate the external boundary before widening the test
suite.
Hand general environment, lockfile, lint, type-check, packaging, or CI failures
to diagnose-python-project, python-package-workflow, or
python-ci-workflow rather than turning this into a generic maintenance skill.
Output Shape
Return:
Test boundary: unit, integration, client, artifact, or full suite.
Command: exact uv command and package or path scope.
Configuration: markers, fixtures, async support, or no change.
Evidence: tests added or run and concise results.
Residual risk: live dependency, unrun integration lane, coverage, or CI
limitation.
Guardrails
- Do not add coverage tooling or thresholds without a concrete need.
- Do not make unit tests depend on a live network, production service, or
machine-local secret.
- Do not use
sys.path edits to hide a package-layout problem.
- Do not leave the old
uv-pytest-unit-testing skill name, profile path, or
routing surface behind after this rename.
References
1---2name: python-testing-workflow3description: Set up, run, and improve Python tests in uv projects and workspaces. Use for pytest configuration, focused and package-targeted runs, fixtures, parametrization, async and integration tests, coverage, CI parity, or failure triage.4license: Apache-2.05---67# Python Testing Workflow89## Purpose1011Make Python tests describe behavior, run through `uv`, and give a focused12failure signal. Preserve the repository's existing test framework and markers;13use the repository's own checked-in commands for setup and execution.1415## Workflow16171. Inspect `pyproject.toml`, existing tests, CI, markers, fixtures, package18 layout, and workspace members before changing test configuration.192. Choose the smallest useful test boundary:20 - unit tests for pure behavior and fakeable dependencies;21 - integration tests for framework, database, filesystem, network, or22 process boundaries;23 - a client test for public HTTP or MCP behavior;24 - a package-artifact smoke test when package contents changed.253. Run a focused check first:26 ```bash27 uv run pytest tests/unit28 uv run pytest -k "auth and not slow"29 uv run --package <member-name> pytest30 ```314. Add fixtures for reusable setup, keep their scope minimal, and use32 `@pytest.mark.parametrize` for input/output matrices.335. Use `monkeypatch`, dependency overrides, fakes, or disposable services at34 the boundary rather than mutating committed configuration or calling a live35 dependency during every test.366. Use async tests only when the code under test is async. Configure the37 repository's async test support explicitly and verify lifespan behavior when38 the app owns startup or shutdown resources.397. Run the relevant complete test selection, then the project's CI-equivalent40 validation commands. Add coverage only when the user or repository has a41 concrete coverage threshold or reporting need.4243## FastAPI And FastMCP Boundaries4445For FastAPI, override external dependencies with46`app.dependency_overrides`, reset them after the test, and use an async client47when the test itself needs async behavior. Ensure lifespan events run when the48application depends on them.4950For FastMCP, prefer an in-memory `Client(mcp)` test for deterministic server51behavior, then add transport or authorization integration tests only for the52configured deployment shape. Test listed and callable tools, readable53resources, and rendered prompts separately when each surface is public.5455## Failure Triage5657Classify the first failure before changing code:5859- collection or import failure: package layout, test path, missing dependency,60 or environment;61- fixture or marker failure: configuration, scope, registration, or setup;62- async/lifespan failure: event-loop ownership, startup, shutdown, or client63 configuration;64- assertion failure: behavior, test data, or an intentionally changed public65 contract;66- integration failure: isolate the external boundary before widening the test67 suite.6869Hand general environment, lockfile, lint, type-check, packaging, or CI failures70to `diagnose-python-project`, `python-package-workflow`, or71`python-ci-workflow` rather than turning this into a generic maintenance skill.7273## Output Shape7475Return:76771. `Test boundary`: unit, integration, client, artifact, or full suite.782. `Command`: exact `uv` command and package or path scope.793. `Configuration`: markers, fixtures, async support, or no change.804. `Evidence`: tests added or run and concise results.815. `Residual risk`: live dependency, unrun integration lane, coverage, or CI82 limitation.8384## Guardrails8586- Do not add coverage tooling or thresholds without a concrete need.87- Do not make unit tests depend on a live network, production service, or88 machine-local secret.89- Do not use `sys.path` edits to hide a package-layout problem.90- Do not leave the old `uv-pytest-unit-testing` skill name, profile path, or91 routing surface behind after this rename.9293## References9495- `references/pytest-workflow.md`96- `references/uv-workspace-testing.md`97- [pytest documentation](https://docs.pytest.org/en/stable/)98- [FastAPI async tests](https://fastapi.tiangolo.com/advanced/async-tests/)99- [FastAPI dependency overrides](https://fastapi.tiangolo.com/advanced/testing-dependencies/)100- [FastMCP server testing](https://gofastmcp.com/servers/testing)