Files
hermes-agent/tests/test_os_marker_gating.py
ethernet cd4317b449 test: convert the last host-OS fakes and guard double markers
Six test files still selected an OS branch with a faked host. Each one now
carries the marker for the host that owns the branch, or derives the
expectation from the real host:

- test_clipboard: macos_only on the has_clipboard_image dispatch. The fake
  picked the branch, but _macos_has_image needs osascript.
- test_claw: windows_only on the tasklist/powershell scan, with return_value
  in place of a side_effect list that pinned the call count.
- test_linux_desktop_entry: the parametrize over "darwin"/"win32" becomes one
  marked test per host. A fake left POSIX paths and a POSIX XDG layout.
- test_graphical_browser_detection: linux_only on the display-server arm. The
  $BROWSER check runs before the platform branch, so its test stays unmarked.
- test_auth_nous_provider: the fixture pinned linux so the macOS certifi
  fallback could not change the result. The assertion now reads the host, so
  the macOS lane covers the fallback too.
- test_tts_macos_output and test_voice_mode: the afplay policy exists because
  CoreAudio init raises a TCC prompt, which no Linux runner reproduces.

tests/conftest.py refuses collection when one test carries two OS markers.
Each marker skips on all but one host, so two of them make a test that runs
nowhere while every lane reports green. tests/test_os_marker_gating.py pins
that behavior.

The docstring on TestConfirmDestructiveSlash said the Windows job runs it.
The class has no marker, so -m windows_only deselects it.
2026-08-09 22:09:49 -04:00

61 lines
1.9 KiB
Python

"""The collection guard against a test carrying two host-OS markers.
Every marker in ``_OS_MARKS`` skips on all but one host, so two of them on one
item means it runs on no host at all while both the Linux suite and the
tests-os lanes report green. tests/conftest.py fails collection instead; this
pins that behaviour so the guard can't be dropped silently.
"""
from __future__ import annotations
import pytest
from tests.conftest import _OS_MARKS, _reject_multiple_os_marks
class _FakeItem:
"""Stands in for a collected item: the guard reads only these two."""
def __init__(self, nodeid: str, *marks: str) -> None:
self.nodeid = nodeid
self._marks = [getattr(pytest.mark, name).mark for name in marks]
def iter_markers(self):
return iter(self._marks)
def test_single_os_marker_is_accepted():
items = [_FakeItem(f"t.py::test_{name}", name) for name in _OS_MARKS]
_reject_multiple_os_marks(items) # must not raise
def test_unmarked_and_non_os_markers_are_accepted():
_reject_multiple_os_marks([
_FakeItem("t.py::test_plain"),
_FakeItem("t.py::test_other", "slow", "integration"),
])
def test_two_os_markers_fail_collection():
items = [
_FakeItem("t.py::test_ok", "linux_only"),
_FakeItem("t.py::test_bad", "linux_only", "windows_only"),
]
with pytest.raises(pytest.UsageError) as excinfo:
_reject_multiple_os_marks(items)
message = str(excinfo.value)
assert "t.py::test_bad" in message
assert "linux_only, windows_only" in message
# The passing item must not be named — the error is a list of offenders.
assert "t.py::test_ok" not in message
def test_all_three_markers_are_reported_together():
item = _FakeItem("t.py::test_worst", *_OS_MARKS)
with pytest.raises(pytest.UsageError) as excinfo:
_reject_multiple_os_marks([item])
for name in _OS_MARKS:
assert name in str(excinfo.value)