Skip to content

Commit 48bc03d

Browse files
committed
Fix the preflight summary counts not adding up
The origin split describes every check that ran, so hanging it off the passed count read as arithmetic that does not work: "10 passed (6 static and 5 dynamic)" when 11 checks ran and one failed. The line now reports what ran and then what came of it -- "11 checks ran (6 static, 5 dynamic) — 10 passed, 0 blocking, 2 warnings." Also pins the end-to-end guarantee for the case that motivated the severity change on the server: an error-severity service check that fails stops the render and names the service and the fix, rather than letting the render spend its budget failing every test.
1 parent a9fb544 commit 48bc03d

4 files changed

Lines changed: 68 additions & 6 deletions

File tree

‎env_check/report.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def print_report(report: PreflightReport, verbose: bool = False) -> None:
5959

6060
if not has_findings and not verbose:
6161
console.info(
62-
f"✓ {HEADER}: {len(report.passed)} checks passed ({report.describe_composition()}).",
62+
f"✓ {HEADER}: {len(report.results)} checks passed ({report.describe_composition()}).",
6363
color=SUCCESS_COLOR,
6464
)
6565
_print_skipped(report, verbose)
@@ -84,7 +84,8 @@ def print_report(report: PreflightReport, verbose: bool = False) -> None:
8484
_print_advisory(advisory)
8585

8686
console.info(
87-
f"\n {len(report.passed)} passed ({report.describe_composition()}), "
87+
f"\n {len(report.results)} checks ran ({report.describe_composition()}) — "
88+
f"{len(report.passed)} passed, "
8889
f"{len(blocking) + len(blocking_advisories)} blocking, "
8990
f"{len(warnings) + len(warning_advisories)} warnings.\n"
9091
)

‎env_check/types.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,9 @@ def count_by_origin(self, origin: str) -> int:
123123
return sum(1 for result in self.results if result.check.origin == origin)
124124

125125
def describe_composition(self) -> str:
126-
"""Describe how many checks came from each origin, for the log."""
127-
return f"{self.count_by_origin(ORIGIN_STATIC)} static and " f"{self.count_by_origin(ORIGIN_DYNAMIC)} dynamic"
126+
"""Describe how many of the checks that ran came from each origin.
127+
128+
This counts every result, passed or not, so it belongs next to the number
129+
of checks that ran rather than the number that passed.
130+
"""
131+
return f"{self.count_by_origin(ORIGIN_STATIC)} static, {self.count_by_origin(ORIGIN_DYNAMIC)} dynamic"

‎tests/test_env_check_origin.py‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_a_report_counts_each_origin_separately(self):
8181

8282
assert report.count_by_origin(ORIGIN_STATIC) == 1
8383
assert report.count_by_origin(ORIGIN_DYNAMIC) == 2
84-
assert report.describe_composition() == "1 static and 2 dynamic"
84+
assert report.describe_composition() == "1 static, 2 dynamic"
8585

8686

8787
class TestOriginInOutput:
@@ -93,7 +93,29 @@ def test_the_summary_names_both_kinds(self, capsys):
9393

9494
print_report(report)
9595

96-
assert "1 static and 0 dynamic" in capsys.readouterr().out
96+
assert "1 static, 0 dynamic" in capsys.readouterr().out
97+
98+
def test_the_counts_add_up_when_a_check_fails(self, capsys):
99+
"""The origin split describes every check that ran, not just the ones that passed."""
100+
passed = CheckSpec(
101+
id="git", type="command_available", severity=SEVERITY_ERROR, description="git", origin=ORIGIN_STATIC
102+
)
103+
failed = CheckSpec(
104+
id="svc",
105+
type="tcp_service_reachable",
106+
severity=SEVERITY_WARNING,
107+
description="storage service",
108+
origin=ORIGIN_DYNAMIC,
109+
)
110+
report = PreflightReport(
111+
results=[CheckResult(passed, STATUS_PASSED, "found"), CheckResult(failed, STATUS_FAILED, "refused")]
112+
)
113+
114+
print_report(report)
115+
output = capsys.readouterr().out
116+
117+
assert "2 checks ran (1 static, 1 dynamic)" in output
118+
assert "1 passed" in output
97119

98120
def test_a_finding_says_which_kind_of_check_produced_it(self, capsys):
99121
check = CheckSpec(

‎tests/test_env_check_render_wiring.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,38 @@ def test_render_module_checks_the_environment_before_doing_any_work(monkeypatch,
118118
renderer.render_module()
119119

120120
assert rendered == []
121+
122+
123+
def test_an_unreachable_local_service_stops_the_render(monkeypatch):
124+
"""A service the tests depend on is a blocking finding, not a note to skim past.
125+
126+
The whole point of the preflight is that a render which cannot pass a single
127+
test never starts. This mirrors a real plan: the test requirements name a
128+
storage service on localhost:6001 that the tests do not mock, the service is
129+
down, and the render must stop with the reason rather than spend its budget
130+
failing every conformance test.
131+
"""
132+
check = CheckSpec(
133+
id="storage-service",
134+
type="tcp_service_reachable",
135+
severity=SEVERITY_ERROR,
136+
description="Storage Service is reachable on port 6001",
137+
args={"host": "localhost", "port": 6001},
138+
reason="The test requirements say the tests talk to the storage service unmocked.",
139+
remediation={"default": "Start the storage service on localhost:6001."},
140+
)
141+
report = PreflightReport(
142+
results=[CheckResult(check, STATUS_FAILED, "localhost:6001 is not reachable ([Errno 61] Connection refused)")]
143+
)
144+
145+
monkeypatch.setattr(module_renderer_module, "run_environment_preflight", lambda *a, **kw: report)
146+
monkeypatch.setattr(module_renderer_module, "print_report", lambda *a, **kw: None)
147+
148+
event_bus = RecordingEventBus()
149+
with pytest.raises(EnvironmentCheckFailed) as raised:
150+
make_renderer(event_bus)._verify_environment()
151+
152+
message = str(raised.value)
153+
assert "Storage Service is reachable on port 6001" in message
154+
assert "Start the storage service on localhost:6001." in message
155+
assert event_bus.published[-1].passed is False

0 commit comments

Comments
 (0)