Skip to content

Commit ff50351

Browse files
authored
ci: run strict-no-cover in scripts/test to catch stale pragmas locally (#2305)
1 parent 1a2244f commit ff50351

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

CLAUDE.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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()`

scripts/test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ uv run --frozen coverage erase
66
uv run --frozen coverage run -m pytest -n auto $@
77
uv run --frozen coverage combine
88
uv run --frozen coverage report
9+
# strict-no-cover spawns `uv run coverage json` internally without --frozen;
10+
# UV_FROZEN=1 propagates to that subprocess so it doesn't touch uv.lock.
11+
UV_FROZEN=1 uv run --frozen strict-no-cover

0 commit comments

Comments
 (0)