This commit is contained in:
John Lancaster
2026-06-16 23:39:45 -05:00
parent 8ada18b7fd
commit c8906cef7b
5 changed files with 269 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
---
icon: simple/markdown
---
# Markdown in 5min
## Headers
```
# H1 Header
## H2 Header
### H3 Header
#### H4 Header
##### H5 Header
###### H6 Header
```
## Text formatting
```
**bold text**
*italic text*
***bold and italic***
~~strikethrough~~
`inline code`
```
## Links and images
```
[Link text](https://example.com)
[Link with title](https://example.com "Hover title")
![Alt text](image.jpg)
![Image with title](image.jpg "Image title")
```
## Lists
```
Unordered:
- Item 1
- Item 2
- Nested item
Ordered:
1. First item
2. Second item
3. Third item
```
## Blockquotes
```
> This is a blockquote
> Multiple lines
>> Nested quote
```
## Code blocks
````
```javascript
function hello() {
console.log("Hello, world!");
}
```
````
## Tables
```
| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Row 1 | Data | Data |
| Row 2 | Data | Data |
```
## Horizontal rule
```
---
or
***
or
___
```
## Task lists
```
- [x] Completed task
- [ ] Incomplete task
- [ ] Another task
```
## Escaping characters
```
Use backslash to escape: \* \_ \# \`
```
## Line breaks
```
End a line with two spaces
to create a line break.
Or use a blank line for a new paragraph.
```
+136
View File
@@ -0,0 +1,136 @@
---
name: pytest-scaffolding
description: "Scaffold a maintainable, hierarchical pytest suite for core functionality first, then extend safely. Use when setting up tests, organizing fixtures by dependency, mirroring src structure in tests, or enforcing fast-by-default test runs."
argument-hint: "Target scope (for example: app/services/job, app/ai, or full repo)"
---
# Pytest Scaffolding
Create test scaffolding that is:
- Hierarchical: test layout roughly mirrors source layout.
- Fast by default: most tests run in under a second total for core units.
- Dependency-aware: slow/external dependencies are isolated behind markers and fixture scope.
- Extensible: minimal initial skeleton supports adding detailed tests later without refactors.
This repository currently uses:
- `uv run pytest` as the canonical test invocation.
- `pyproject.toml` pytest config under `[tool.pytest.ini_options]`.
- strict marker checking (`--strict-markers`).
Load [pytest references](./references/pytest-docs.md) when you need detailed rules.
## When To Use
- Bootstrapping tests for a new or existing Python repo.
- Reorganizing tests that have become flat, slow, or difficult to extend.
- Defining fixture boundaries before writing many assertions.
- Creating only the first-layer scaffold for core behavior (not exhaustive coverage yet).
## Inputs To Collect
1. Target test scope: full repo, package, or module.
2. Dependency profile: pure Python, DB, network/API, filesystem, UI/browser.
3. Runtime expectation: what must be instant vs allowed to be slower.
4. CI policy: which marker groups must block merges.
If these are missing, ask concise clarifying questions before editing.
## Workflow
1. Map source tree to test tree.
2. Classify tests by dependency cost.
3. Create minimal directories and placeholder test modules.
4. Create fixture layers (`tests/conftest.py` plus local `conftest.py` in subtrees only when needed).
5. Register markers and default selection behavior.
6. Run collection and fast path tests.
7. Report gaps and next extension points.
## Step 1: Map Source To Tests
Create a mirrored structure rooted at `tests/` that follows major source concepts.
Example mapping pattern:
- `src/app/services/job.py` -> `tests/app/services/test_job.py`
- `src/app/ai/graphs/transcription.py` -> `tests/app/ai/graphs/test_transcription.py`
- `src/app/api/routes.py` -> `tests/app/api/test_routes.py`
Rules:
- One initial test module per core source module.
- Prefer `test_<module>.py` naming.
- Keep directory mirrors shallow first; add deeper modules only where behavior is complex.
## Step 2: Classify By Dependency Cost
Assign each test module to one initial class:
- `unit`: no DB/network/filesystem side effects; instant execution.
- `integration`: touches DB, HTTP stack, workflow runtime, or external services.
- `smoke`: thin end-to-end confidence checks.
Decision logic:
- If logic can run with fakes/stubs, make it `unit`.
- If contract with framework/DB is essential, make it `integration`.
- If validating a user-critical path across layers, make it `smoke`.
## Step 3: Scaffold Minimal Test Modules
For each target module, scaffold:
- import section
- one happy-path test function
- one error/edge test function
- TODO comments indicating detail expansion points
Keep assertions minimal but behavior-focused. Avoid large fixtures in module files.
## Step 4: Fixture Layering Strategy
Use fixture scopes based on cost:
- `function` scope by default.
- broader scopes (`module`/`session`) only for expensive setup with clear teardown.
Layer fixtures by directory:
- `tests/conftest.py`: global, lightweight fixtures only (factories, deterministic defaults).
- subtree `conftest.py`: domain-specific fixtures (API client, DB session, AI runtime stubs).
Guidelines:
- Prefer yield fixtures for setup/teardown.
- Keep fixtures atomic (one state-changing responsibility per fixture).
- Avoid autouse except for truly universal behavior.
## Step 5: Marker Taxonomy And Config
Ensure marker names are explicit and registered in `pyproject.toml` because strict markers are enabled.
Recommended baseline markers:
- `unit`
- `integration`
- `smoke`
- `slow`
- `external` (requires network/service credentials)
Default run strategy:
- Fast local path: run only `unit` by default in day-to-day iteration.
- Full validation path: run all markers in CI or pre-release checks.
## Step 6: Execution And Verification
Run commands in this order:
1. `uv run pytest --collect-only -q`
2. `uv run pytest -m unit -q`
3. `uv run pytest -q` (if dependencies are available)
Optional targeted runs:
- by node id for one test
- by `-k` expression for focused iteration
## Step 7: Completion Checks
A scaffold pass is complete when all are true:
1. Every core source area has at least one corresponding test module.
2. Unit tests run quickly and deterministically.
3. Integration/external tests are isolated by marker and fixture boundaries.
4. No unregistered marker warnings/errors.
5. `tests/` structure is understandable without extra documentation.
6. A clear TODO path exists for deepening assertions later.
## Branching Scenarios
- If external APIs are required: provide stubs/mocks for unit tests; guard real calls behind `external` marker.
- If DB is required: build a dedicated integration fixture layer and keep unit tests DB-free.
- If tests become slow: split slow tests via marker and widen fixture scope only where safe.
- If naming conflicts appear: keep unique test module names or package test directories explicitly.
## Output Format
When applying this skill, provide:
1. Proposed test tree diff.
2. Marker and fixture plan.
3. Exact commands for fast path and full path.
4. Risks/open questions before writing detailed assertions.
@@ -0,0 +1,22 @@
# Pytest Documentation Notes
Primary references used:
- https://docs.pytest.org/en/stable/explanation/goodpractices.html
- https://docs.pytest.org/en/stable/how-to/fixtures.html
- https://docs.pytest.org/en/stable/example/markers.html
- https://docs.pytest.org/en/stable/reference/customize.html
- https://docs.pytest.org/en/stable/explanation/flaky.html
## Practical Guidance For This Skill
- Use src-aligned test layout and keep test discovery conventional.
- Keep fixtures small, composable, and explicit; use `yield` for teardown.
- Register custom markers and keep strict marker validation on.
- Separate quick unit runs from slower integration/external runs.
- Minimize flakiness by controlling shared state and avoiding hidden dependencies.
- Use `--collect-only` and marker-filtered runs to validate scaffold quality early.
## Commands Worth Remembering
- `uv run pytest --collect-only -q`
- `uv run pytest -m unit -q`
- `uv run pytest -m "not external" -q`
- `uv run pytest -q`