From 2662bfb7560d6e50cbdee4e86970c5f9f77d14cd Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Thu, 30 Apr 2026 02:46:56 -0700 Subject: [PATCH] fix(tests): make test_update_stale_dashboard immune to hermes_cli.main reload (#17881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six tests in this file failed in CI (-n auto) after #17832 landed because other tests on the same xdist worker reload hermes_cli.main: tests/hermes_cli/test_env_loader.py:85-86 sys.modules.pop('hermes_cli.main', None) importlib.import_module('hermes_cli.main') tests/hermes_cli/test_skills_subparser.py:24-25 del sys.modules['hermes_cli.main'] When either ran first on a worker, our top-of-file 'from hermes_cli.main import _kill_stale_dashboard_processes' captured a stale function object whose __globals__ points at the old module dict. patch('hermes_cli.main._find_stale_dashboard_pids', ...) then patched the new module, but the stale function resolved the dependency via its stale __globals__, so every patch became a no-op: pids=[] → early return → no signals, no output, assertions failed. Fix: add an autouse fixture that rebinds the three module-level names to whatever is currently live in sys.modules['hermes_cli.main'] before each test runs. The pollutants in the other two files are load-bearing for their own tests, so fixing it on the consumer side is correct. Repro: pytest tests/hermes_cli/test_env_loader.py tests/hermes_cli/test_update_stale_dashboard.py --- .../hermes_cli/test_update_stale_dashboard.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/hermes_cli/test_update_stale_dashboard.py b/tests/hermes_cli/test_update_stale_dashboard.py index d2b6fd63a0..546fd48991 100644 --- a/tests/hermes_cli/test_update_stale_dashboard.py +++ b/tests/hermes_cli/test_update_stale_dashboard.py @@ -13,6 +13,7 @@ History: from __future__ import annotations +import importlib import os import sys from unittest.mock import patch, MagicMock, call @@ -26,6 +27,38 @@ from hermes_cli.main import ( ) +@pytest.fixture(autouse=True) +def _refresh_bindings_against_live_module(): + """Rebind module-level names to the *current* ``hermes_cli.main``. + + Other tests in the suite (notably ``test_env_loader.py`` and + ``test_skills_subparser.py``) reload or delete ``hermes_cli.main`` from + ``sys.modules``. When that happens on the same xdist worker before we + run, our top-of-file ``from hermes_cli.main import ...`` bindings end + up pointing at the *old* module object. ``patch(\"hermes_cli.main.X\")`` + then patches the *new* module, but the function we call still resolves + ``_find_stale_dashboard_pids`` via its stale ``__globals__``, so every + patch becomes a no-op and the kill path silently returns early. + + Refreshing the bindings (and the patch target) to the live module + object — and keeping them consistent — makes the tests immune to + ordering within the worker. The fix lives in the test module because + the two pollutants above are load-bearing for their own tests. + """ + global _find_stale_dashboard_pids + global _kill_stale_dashboard_processes + global _warn_stale_dashboard_processes + + live = sys.modules.get("hermes_cli.main") + if live is None: + live = importlib.import_module("hermes_cli.main") + + _find_stale_dashboard_pids = live._find_stale_dashboard_pids + _kill_stale_dashboard_processes = live._kill_stale_dashboard_processes + _warn_stale_dashboard_processes = live._warn_stale_dashboard_processes + yield + + def _ps_line(pid: int, cmd: str) -> str: """Format a line as it would appear in ``ps -A -o pid=,command=`` output.""" return f"{pid:>7} {cmd}"