8FS-508 regression coverage for the lint baseline (snapshot + diff).
12- Validate save_baseline creates a file and returns a count.
13- Validate load_baseline reads back saved data.
14- Validate diff_against_baseline detects new and resolved violations.
15- Validate --baseline and --against-baseline flag behaviour via run_linter.
16- Validate mutually exclusive flag error.
23 L3 — assertion details
28- All baseline files are written to ``tmp_path``; no real project
29 baselines are touched.
32from __future__
import annotations
36from pathlib
import Path
43 diff_against_baseline,
54 """Build mock lint results with specified violations."""
55 by_path: dict[str, list[tuple[str, str]]] = {}
56 for path, rule, msg
in violations:
57 by_path.setdefault(path, []).append((rule, msg))
60 for path, items
in by_path.items():
63 "header",
"docstring",
"diagnostics_profile",
"dbg_usage",
64 "dbg_import",
"func_pattern",
"syntax_warnings",
"type_hints",
65 "no_hardcoded_secrets",
"dbg_assert_safety",
"tests_exist",
67 for rule
in all_rules:
68 failing = [(r, m)
for r, m
in items
if r == rule]
70 checks[rule] = {
"pass":
False,
"message": failing[0][1]}
72 checks[rule] = {
"pass":
True,
"message":
"OK"}
74 "header": checks[
"header"][
"pass"],
75 "docstring": checks[
"docstring"][
"pass"],
76 "diagnostics_profile": checks[
"diagnostics_profile"][
"pass"],
77 "dbg_usage": checks[
"dbg_usage"][
"pass"],
78 "dbg_import": checks[
"dbg_import"][
"pass"],
79 "func_pattern": checks[
"func_pattern"][
"pass"],
80 "syntax_warnings": checks[
"syntax_warnings"][
"pass"],
81 "type_hints": checks[
"type_hints"][
"pass"],
82 "no_hardcoded_secrets": checks[
"no_hardcoded_secrets"][
"pass"],
83 "dbg_assert_safety": checks[
"dbg_assert_safety"][
"pass"],
84 "tests_exist": checks[
"tests_exist"][
"pass"],
85 "compliant": all(c[
"pass"]
for c
in checks.values()),
92 "compliant": all(c[
"pass"]
for c
in checks.values()),
106 results =
_make_results([(
"foo.py",
"header",
"bad shebang")])
107 bp = tmp_path /
"baseline.json"
108 count = save_baseline(results, bp,
"strict")
114 (
"a.py",
"header",
"bad"),
115 (
"a.py",
"docstring",
"missing"),
116 (
"b.py",
"header",
"wrong"),
118 bp = tmp_path /
"baseline.json"
119 count = save_baseline(results, bp,
"strict")
123 bp = tmp_path /
"deep" /
"nested" /
"baseline.json"
124 save_baseline([], bp,
"strict")
129 bp = tmp_path /
"baseline.json"
130 count = save_baseline(results, bp,
"strict")
141 results =
_make_results([(
"foo.py",
"header",
"bad shebang")])
142 bp = tmp_path /
"baseline.json"
143 save_baseline(results, bp,
"strict")
144 bl = load_baseline(bp)
145 assert bl
is not None
146 assert len(bl.entries) == 1
147 assert bl.entries[0].path ==
"foo.py"
148 assert bl.entries[0].rule ==
"header"
149 assert bl.profile ==
"strict"
152 assert load_baseline(tmp_path /
"nope.json")
is None
155 bp = tmp_path /
"baseline.json"
156 bp.write_text(
"not json!", encoding=
"utf-8")
157 assert load_baseline(bp)
is None
160 bp = tmp_path /
"baseline.json"
161 bp.write_text(json.dumps({
"_schema_version":
"99.0"}), encoding=
"utf-8")
162 assert load_baseline(bp)
is None
174 oct_version=
"0.22.0", timestamp=
"", profile=
"strict",
177 (
"a.py",
"header",
"old issue"),
178 (
"b.py",
"docstring",
"new problem"),
180 new, resolved = diff_against_baseline(current, baseline)
182 assert new[0][0] ==
"b.py"
183 assert new[0][1] ==
"docstring"
191 oct_version=
"0.22.0", timestamp=
"", profile=
"strict",
194 new, resolved = diff_against_baseline(current, baseline)
196 assert len(resolved) == 1
197 assert resolved[0][1] ==
"docstring"
202 oct_version=
"0.22.0", timestamp=
"", profile=
"strict",
205 new, resolved = diff_against_baseline(current, baseline)
207 assert len(resolved) == 0
211 entries=[], oct_version=
"0.22.0", timestamp=
"", profile=
"strict",
214 new, resolved = diff_against_baseline(current, baseline)
216 assert len(resolved) == 0
227 result = run_linter(tmp_path, [
"--baseline",
"--against-baseline"])
229 captured = capsys.readouterr()
230 assert "mutually exclusive" in captured.err
234 result = run_linter(tmp_path, [
"--against-baseline"])
236 captured = capsys.readouterr()
237 assert "no baseline found" in captured.err
test_mutually_exclusive(self, Path tmp_path, capsys)
test_against_baseline_without_file(self, Path tmp_path, capsys)
test_detects_new_violations(self)
test_detects_resolved_violations(self)
test_unchanged_suppressed(self)
test_empty_baseline_everything_is_new(self)
test_load_saved(self, Path tmp_path)
test_nonexistent_returns_none(self, Path tmp_path)
test_wrong_schema_returns_none(self, Path tmp_path)
test_corrupt_returns_none(self, Path tmp_path)
test_returns_violation_count(self, Path tmp_path)
test_zero_violations(self, Path tmp_path)
test_creates_file(self, Path tmp_path)
test_creates_parent_dirs(self, Path tmp_path)
list[dict] _make_results(list[tuple[str, str, str]] violations)