From f34c4cc670bbdbc9583db8d0bee7394825ec6068 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Mon, 22 Jun 2026 08:12:02 +0200 Subject: [PATCH] Fix non-hermetic diet_guard gate tests depending on a real X display test_demo_opens_window and test_bare_gate_due_opens_window never mocked wait_for_display(), so they silently relied on a real, reachable X display being present. On a dev machine this is always true, so they passed; on a true headless CI runner (no X server at all) each test blocked for the real 60s timeout before failing, explaining the CI run's 131s duration. Mocking it to True (matching the existing test_gate_due_but_display_not_ready_defers pattern for the False case) restores hermeticity with no production code change. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01A7vbgtFfZmfxJtN5DdtJky --- ...t-guard-test-isolation-fix-2026-06-22.json | 23 +++++++++++++++++++ python_pkg/diet_guard/tests/test_cli.py | 2 ++ 2 files changed, 25 insertions(+) create mode 100644 docs/superpowers/evidence/diet-guard-test-isolation-fix-2026-06-22.json diff --git a/docs/superpowers/evidence/diet-guard-test-isolation-fix-2026-06-22.json b/docs/superpowers/evidence/diet-guard-test-isolation-fix-2026-06-22.json new file mode 100644 index 0000000..adfaf59 --- /dev/null +++ b/docs/superpowers/evidence/diet-guard-test-isolation-fix-2026-06-22.json @@ -0,0 +1,23 @@ +{ + "intent": "Fix two diet_guard tests that were non-hermetic: they never mocked wait_for_display(), so they silently depended on a real, reachable X display. Discovered when the previous CI-fix commit's first true headless run (no X server) made them block for a real 60s timeout each and then fail.", + "scope": [ + "python_pkg/diet_guard/tests/test_cli.py (TestGate.test_demo_opens_window, TestGate.test_bare_gate_due_opens_window)", + "Non-goal: any change to _cli.py's actual gate logic, which is correct as-is" + ], + "changes": [ + "Added patch.object(_cli, \"wait_for_display\", return_value=True) to both tests, matching the pattern already used in the adjacent test_gate_due_but_display_not_ready_defers test (which mocks it to False for that scenario)" + ], + "verification": [ + { + "command": "time python -m pytest -q (full repo suite)", + "result": "pass", + "evidence": "949 passed, 100% coverage, 14.25s total -- back to normal from the previous CI run's 131s (which included two real 60s blocking waits for the unmocked tests)" + } + ], + "risks": [ + "None -- this restores test hermeticity without changing any production code path" + ], + "rollback": [ + "git revert this commit; the two tests will again depend on a real X display being present, passing on a dev machine but failing/hanging for 60s+ each on headless CI" + ] +} diff --git a/python_pkg/diet_guard/tests/test_cli.py b/python_pkg/diet_guard/tests/test_cli.py index f2a5f16..c2fb9d3 100644 --- a/python_pkg/diet_guard/tests/test_cli.py +++ b/python_pkg/diet_guard/tests/test_cli.py @@ -229,6 +229,7 @@ class TestGate: patch.object(_cli, "MealGate", return_value=gate) as factory, patch.object(_cli, "acquire_gate_lock", return_value=MagicMock()), patch.object(_cli, "release_gate_lock"), + patch.object(_cli, "wait_for_display", return_value=True), ): assert main(["gate", "--demo"]) == 0 factory.assert_called_once_with(demo_mode=True) @@ -248,6 +249,7 @@ class TestGate: patch.object(_cli, "MealGate", return_value=gate), patch.object(_cli, "acquire_gate_lock", return_value=MagicMock()), patch.object(_cli, "release_gate_lock"), + patch.object(_cli, "wait_for_display", return_value=True), ): assert main(["gate"]) == 0 gate.run.assert_called_once()