Skip to content

Commit c3106c0

Browse files
committed
test: codify process-state isolation rules
1 parent d728679 commit c3106c0

2 files changed

Lines changed: 18 additions & 5 deletions

File tree

docs/reference/testing-strategy.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,22 @@ The checked-in JSON Schemas should be exercised both through Pydantic and a
686686
standards-oriented JSON Schema validator. A Pydantic model successfully reading
687687
its own generated schema is not independent contract evidence.
688688

689+
### Pytest antipatterns
690+
691+
- Use `monkeypatch` for process-global state such as `sys.modules`, `sys.argv`,
692+
and environment variables. When restoration is the behavior under test,
693+
assert that the original object or missing state is restored.
694+
- Name the expected exception type and a stable diagnostic instead of using
695+
bare `pytest.raises(Exception)`.
696+
- Assert the observable outcome or independently parsed wire contract; a model
697+
successfully validating its own output is not sufficient evidence.
698+
- Name source-shape checks honestly and reserve them for supported text or
699+
architecture contracts. Do not disguise source substrings as behavior tests.
700+
- Do not add an empty `pytestmark`; markers exist only for execution-affecting
701+
traits owned by the test topology.
702+
- Keep Harbor regressions in their owning dataset and task leaf. Shared
703+
validation modules should contain only suite-wide contracts.
704+
689705
Use the standard library's `tempfile`, `subprocess`, and process primitives for
690706
artifact and replay tests. Do not use an in-memory filesystem or `pyfakefs` to
691707
claim evidence about atomic rename, SQLite WAL recovery, symlink handling, or

tests/unit/tooling/test_ci_planner_catalog.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,10 @@ def _load_script(name: str) -> ModuleType:
3636
def _ci_plan(*args: str) -> dict[str, str]:
3737
classifier = _load_script("classify-ci-paths")
3838
output = io.StringIO()
39-
original_argv = sys.argv
40-
try:
41-
sys.argv = ["classify-ci-paths", *args]
39+
with pytest.MonkeyPatch.context() as process_state:
40+
process_state.setattr(sys, "argv", ["classify-ci-paths", *args])
4241
with contextlib.redirect_stdout(output):
4342
classifier.main()
44-
finally:
45-
sys.argv = original_argv
4643
return dict(line.split("=", 1) for line in output.getvalue().splitlines())
4744

4845

0 commit comments

Comments
 (0)