Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ jobs:
sudo apt install libxkbcommon-x11-0 xvfb libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 x11-utils
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1920x1200x24 -ac +extension GLX
- name: Run the tests
# test_HighContentScreeningGui.py: PySide6 QObject double-init bug (separate issue)
# SQUID_PYTEST_HARD_EXIT: the suite intermittently segfaults during
# interpreter shutdown AFTER all tests pass (Qt destructor order vs
# Python GC — the same crash main_hcs.py avoids with os._exit(); seen
# on master in 3 of the 15 runs before 2026-07-13). The conftest hook
# hard-exits with pytest's real status once the session is complete,
# so real test failures still fail the step.
run: python3 -m pytest --ignore=tests/control/test_HighContentScreeningGui.py
working-directory: ./software
env:
SQUID_PYTEST_HARD_EXIT: "1"
- name: Run the GUI test in its own process
# Own invocation: the full-application GUI test leaves Qt/thread state
# behind that deterministically segfaults later Qt tests (e.g.
# test_channel_sequence) when run in the same pytest process.
# Step-scoped pyqt5 pin: without it, pytest-qt picks PySide6 for qtbot
# while the app code (qtpy) uses PyQt5, and the mixed bindings fail
# with a QObject double-init error.
run: python3 -m pytest tests/control/test_HighContentScreeningGui.py
working-directory: ./software
env:
QT_API: pyqt5
PYTEST_QT_API: pyqt5
SQUID_PYTEST_HARD_EXIT: "1"
23 changes: 23 additions & 0 deletions software/tests/control/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"""

import logging
import os
import sys
from unittest.mock import patch

import pytest
Expand All @@ -16,6 +18,27 @@
logger = logging.getLogger(__name__)


def pytest_sessionfinish(session, exitstatus):
session.config._squid_exitstatus = int(exitstatus)


def pytest_unconfigure(config):
"""Optionally skip interpreter teardown after the test session.

Under PyQt5 on Linux, a pytest process that constructed the full HCS GUI
segfaults during interpreter shutdown (Qt C++ destructor order conflicts
with Python GC) even though every test passed. main_hcs.py sidesteps the
same crash with os._exit(); SQUID_PYTEST_HARD_EXIT=1 lets CI's isolated
GUI-test invocation do likewise, preserving pytest's exit status.
"""
if os.environ.get("SQUID_PYTEST_HARD_EXIT") == "1":
sys.stdout.flush()
sys.stderr.flush()
# Default 1, not 0: if pytest_sessionfinish never ran (e.g. a
# sessionstart failure), an unrecorded status must fail the step.
os._exit(getattr(config, "_squid_exitstatus", 1))


def _make_tracking_init(original_init, instances_list):
"""Create a wrapper that tracks Microcontroller instances."""

Expand Down
Loading