diff --git a/tests/conftest.py b/tests/conftest.py index 2852e385..5bc3e3cf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -99,13 +99,30 @@ def pytest_unconfigure(config: object) -> None: def _smart_watchdog_exit() -> None: import time - if not _pytest_finished_event.wait(timeout=120.0): + if not _pytest_finished_event.wait(timeout=60.0): os._exit(2) - if not _pytest_finished_event.wait(timeout=30.0): + if not _pytest_finished_event.wait(timeout=15.0): os._exit(2) threading.Thread(target=_smart_watchdog_exit, daemon=True, name="conftest-smart-watchdog").start() +def _unconditional_watchdog_exit() -> None: + """Hard fail-safe: fires regardless of pytest state after 90s total. + + The smart watchdog (above) is gated on pytest_unconfigure setting + _pytest_finished_event. If something is hung BEFORE pytest + unconfigure runs (e.g., the conftest's own _warmup_app_controller + hangs in wait_for_warmup during startup, or pytest never reaches + its unconfigure phase), the smart watchdog's first wait + blocks. This unconditional watchdog is the sledgehammer: 90s + from conftest load, fire os._exit(2) regardless. + """ + import time + time.sleep(90.0) + os._exit(2) + +threading.Thread(target=_unconditional_watchdog_exit, daemon=True, name="conftest-unconditional-watchdog").start() + from src.gui_2 import App class VerificationLogger: