@@ -29,18 +29,31 @@ This document contains critical information about working with this codebase. Fo
2929 - IMPORTANT: The ` tests/client/test_client.py ` is the most well designed test file. Follow its patterns.
3030 - IMPORTANT: Be minimal, and focus on E2E tests: Use the ` mcp.client.Client ` whenever possible.
3131 - Coverage: CI requires 100% (` fail_under = 100 ` , ` branch = true ` ).
32- - Full check: ` ./scripts/test ` (~ 20s, matches CI exactly)
33- - Targeted check while iterating:
32+ - Full check: ` ./scripts/test ` (~ 23s). Runs coverage + ` strict-no-cover ` on the
33+ default Python. Not identical to CI: CI also runs 3.10–3.14 × {ubuntu, windows},
34+ and some branch-coverage quirks only surface on specific matrix entries.
35+ - Targeted check while iterating (~ 4s, deterministic):
3436
3537 ``` bash
3638 uv run --frozen coverage erase
3739 uv run --frozen coverage run -m pytest tests/path/test_foo.py
3840 uv run --frozen coverage combine
3941 uv run --frozen coverage report --include=' src/mcp/path/foo.py' --fail-under=0
42+ UV_FROZEN=1 uv run --frozen strict-no-cover
4043 ```
4144
4245 Partial runs can' t hit 100% (coverage tracks `tests/` too), so `--fail-under=0`
43- and `--include` scope the report to what you actually changed.
46+ and `--include` scope the report. `strict-no-cover` has no false positives on
47+ partial runs — if your new test executes a line marked `# pragma: no cover`,
48+ even a single-file run catches it.
49+ - Coverage pragmas:
50+ - `# pragma: no cover` — line is never executed. CI' s ` strict-no-cover` fails if
51+ it IS executed. When your test starts covering such a line, remove the pragma.
52+ - ` # pragma: lax no cover` — excluded from coverage but not checked by
53+ ` strict-no-cover` . Use for lines covered on some platforms/versions but not
54+ others.
55+ - ` # pragma: no branch` — excludes branch arcs only. coverage.py misreports the
56+ ` -> exit` arc for nested ` async with` on Python 3.11+ (worse on 3.14/Windows).
4457 - Avoid `anyio.sleep ()` with a fixed duration to wait for async operations. Instead:
4558 - Use ` anyio.Event` — set it in the callback/handler, ` await event.wait ()` in the test
4659 - For stream messages, use ` await stream.receive ()` instead of ` sleep()` + ` receive_nowait()`
0 commit comments