Coverage for /home/crpier/Projects/snektest/snektest/agent_docs.py: 35%
20 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-07 00:30 +0300
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-07 00:30 +0300
1"""Embedded documentation and examples for coding agents."""
3from importlib.resources import files
5from snektest.models import BadRequestError
7AGENT_DOCS = """# snektest agent guide
9Snektest is a Python testing framework with first-class async and typing support.
11## Quick start
13Create a `test_*.py` file and decorate test functions with `@test(mark=...)`. Mark every test with the resources it may use:
15```python
16from snektest import assert_eq, test
18@test(mark="fast")
19def test_addition() -> None:
20 assert_eq(1 + 1, 2)
21```
23Run tests with:
25```bash
26snektest
27python -m snektest
28```
30Useful commands:
32```bash
33snektest --help
34snektest --agent-docs
35snektest --examples
36snektest --example async
37snektest examples
38snektest example async
39```
41## Core patterns
43- Import assertions from `snektest`; prefer `assert_eq()` over bare `assert`.
44- Mark every test. This is the recommended way to use snektest.
45- Use `mark="fast"` for in-memory tests with no IO, threads, or subprocesses.
46- Use `mark="medium"` for tests that use local IO or threads.
47- Use `mark="slow"` for tests that use network IO, subprocesses, or expensive external resources.
48- Async tests are regular `async def` functions decorated with `@test(mark=...)`.
49- Use `Param(value=..., name=...)` inside `@test([...], mark=...)` for parameterization.
50- Use generator fixtures with `load_fixture(fixture())`.
51- Put all `load_fixture(...)` calls at the beginning of the test, before actions or assertions.
52- Avoid conditional or mid-test fixture loading unless delayed loading is the behavior under test.
53- Annotate shared fixtures as `SessionFixture[T]` or `AsyncSessionFixture[T]` for setup shared by the whole test run.
54- Filter runs with paths such as `snektest tests/test_math.py::test_addition` or markers such as `snektest --mark fast`.
56## Copyable examples
58List bundled examples:
60```bash
61snektest --examples
62```
64Print one example:
66```bash
67snektest --example basic
68snektest --example fixtures
69snektest --example async
70snektest --example parametrize
71```
72"""
74EXAMPLE_FILES: dict[str, str] = {
75 "async": "async_tests.py",
76 "basic": "basic_test.py",
77 "fixtures": "fixtures.py",
78 "parametrize": "parametrize.py",
79}
82def get_agent_docs() -> str:
83 """Return the embedded guide for AI agents and humans."""
84 return AGENT_DOCS
87def get_examples_listing() -> str:
88 """Return a human-readable list of bundled examples."""
89 lines = [
90 "Bundled snektest examples:",
91 *[f" {name:<12} snektest --example {name}" for name in sorted(EXAMPLE_FILES)],
92 ]
93 return "\n".join(lines) + "\n"
96def get_example_source(example_name: str) -> str:
97 """Return the source code for a bundled example."""
98 normalized_name = example_name.removesuffix(".py")
99 file_name = EXAMPLE_FILES.get(normalized_name)
100 if file_name is None:
101 file_name = next(
102 (
103 candidate
104 for candidate in EXAMPLE_FILES.values()
105 if candidate.removesuffix(".py") == normalized_name
106 ),
107 None,
108 )
109 if file_name is None:
110 available = ", ".join(sorted(EXAMPLE_FILES))
111 msg = f"Unknown example `{example_name}`. Use one of: {available}"
112 raise BadRequestError(msg)
114 resource = files("snektest.examples").joinpath(file_name)
115 return resource.read_text(encoding="utf-8")