Fix the real cause of the wake_alarm CI coverage gap

The previous two fix attempts (removing -n 4 xdist parallelism, ruling
out a Python 3.12-vs-3.14 difference) both targeted the wrong cause for
the coverage gap on _alarm_display.py:71. The actual bug:
_restore_display() was never mocked in the _block_extra_devices fixture
shared by test_alarm_part2/3/4.py, so every test exercising
on_close()/_lock.close() ran the REAL _restore_display(), which calls
the REAL shutil.which('xset'). My dev machine has /usr/bin/xset
installed, so it always hit the "found" branch by accident; the CI
runner doesn't, so it always hit the "missing" branch instead, and
there was no dedicated unit test for the "found" path at all.

Fix: mock _restore_display in that fixture (matching its already-mocked
siblings _restore_fans/_restore_alarm_audio/turn_off_plug), and add a
dedicated, hermetic test for the xset-found branch that doesn't depend
on whether the running machine actually has xset on PATH. Side benefit:
the test suite no longer makes a real `xset s on` subprocess call on
the developer's desktop as an untracked side effect of running tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A7vbgtFfZmfxJtN5DdtJky
This commit is contained in:
Krzysztof kuhy Rudnicki 2026-06-22 09:14:29 +02:00
parent 3a2e63af9c
commit dd01b6f846
4 changed files with 20 additions and 0 deletions

View File

@ -127,3 +127,20 @@ class TestDisplayHelpers:
): ):
_restore_display() _restore_display()
mock_run.assert_not_called() mock_run.assert_not_called()
def test_restore_display_runs_xset_s_on_when_present(self) -> None:
"""_restore_display re-enables the screensaver via xset when present."""
with (
patch(
"python_pkg.wake_alarm._alarm_display.shutil.which",
return_value="/usr/bin/xset",
),
patch("python_pkg.wake_alarm._alarm_display.subprocess.run") as mock_run,
):
_restore_display()
mock_run.assert_called_once_with(
["/usr/bin/xset", "s", "on"],
check=False,
capture_output=True,
timeout=5,
)

View File

@ -59,6 +59,7 @@ def _block_extra_devices() -> Generator[MagicMock]:
patch("python_pkg.wake_alarm._alarm._restore_fans"), patch("python_pkg.wake_alarm._alarm._restore_fans"),
patch("python_pkg.wake_alarm._alarm._set_max_brightness"), patch("python_pkg.wake_alarm._alarm._set_max_brightness"),
patch("python_pkg.wake_alarm._alarm._wake_display"), patch("python_pkg.wake_alarm._alarm._wake_display"),
patch("python_pkg.wake_alarm._alarm._restore_display"),
patch("python_pkg.wake_alarm._alarm._warn_if_no_real_sink"), patch("python_pkg.wake_alarm._alarm._warn_if_no_real_sink"),
patch("python_pkg.wake_alarm._alarm._activate_alarm_audio", return_value=None), patch("python_pkg.wake_alarm._alarm._activate_alarm_audio", return_value=None),
patch("python_pkg.wake_alarm._alarm._restore_alarm_audio"), patch("python_pkg.wake_alarm._alarm._restore_alarm_audio"),

View File

@ -58,6 +58,7 @@ def _block_extra_devices() -> Generator[MagicMock]:
patch("python_pkg.wake_alarm._alarm._restore_fans"), patch("python_pkg.wake_alarm._alarm._restore_fans"),
patch("python_pkg.wake_alarm._alarm._set_max_brightness"), patch("python_pkg.wake_alarm._alarm._set_max_brightness"),
patch("python_pkg.wake_alarm._alarm._wake_display"), patch("python_pkg.wake_alarm._alarm._wake_display"),
patch("python_pkg.wake_alarm._alarm._restore_display"),
patch("python_pkg.wake_alarm._alarm._warn_if_no_real_sink"), patch("python_pkg.wake_alarm._alarm._warn_if_no_real_sink"),
patch("python_pkg.wake_alarm._alarm._activate_alarm_audio", return_value=None), patch("python_pkg.wake_alarm._alarm._activate_alarm_audio", return_value=None),
patch("python_pkg.wake_alarm._alarm._restore_alarm_audio"), patch("python_pkg.wake_alarm._alarm._restore_alarm_audio"),

View File

@ -56,6 +56,7 @@ def _block_extra_devices() -> Generator[MagicMock]:
patch("python_pkg.wake_alarm._alarm._restore_fans"), patch("python_pkg.wake_alarm._alarm._restore_fans"),
patch("python_pkg.wake_alarm._alarm._set_max_brightness"), patch("python_pkg.wake_alarm._alarm._set_max_brightness"),
patch("python_pkg.wake_alarm._alarm._wake_display"), patch("python_pkg.wake_alarm._alarm._wake_display"),
patch("python_pkg.wake_alarm._alarm._restore_display"),
patch("python_pkg.wake_alarm._alarm._warn_if_no_real_sink"), patch("python_pkg.wake_alarm._alarm._warn_if_no_real_sink"),
patch("python_pkg.wake_alarm._alarm._activate_alarm_audio", return_value=None), patch("python_pkg.wake_alarm._alarm._activate_alarm_audio", return_value=None),
patch("python_pkg.wake_alarm._alarm._restore_alarm_audio"), patch("python_pkg.wake_alarm._alarm._restore_alarm_audio"),