You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix test hangs on Linux/macOS CI by mocking system dependencies (#2353)
* Fix flaky integration tests in test_init.py
The tests test_create_repo and test_add_existing_repo were failing
intermittently with RepoModelDoesNotExist and waitUntil timeout errors.
Root cause: The tests used is_worker_running() which returns False as
soon as current_job is None, but worker threads may still be alive and
Qt signals may not be fully processed yet.
Fix: Adopt the same reliable waiting patterns used in unit tests:
- Add all_workers_finished() helper that checks worker.is_alive()
- Add disconnect_all() helper for proper signal cleanup
- Call QCoreApplication.processEvents() after waiting for workers
- Update init_db fixture teardown to properly clean up state
* Test reliability fixes
* Fix pythonpath
* Skip D-Bus calls during tests to fix CI hangs
D-Bus calls to systemd-logind and NetworkManager can hang indefinitely
in CI environments where D-Bus is partially available. Check for
sys._called_from_test (set by pytest) and skip these operations.
* Add debug logging to diagnose CI hang
Print statements at key initialization points to identify where
the test hang occurs in Linux Python 3.12 CI environment.
* Add more debug logging to init_db fixture and MainWindow
Track where hang occurs between VortaApp creation and test execution.
* Add debug to test function and fixture yield
Check if test function is ever reached after fixture setup.
* Add debug logging to init_db teardown
Pinpoint where hang occurs in fixture teardown.
* Replace qtbot.waitUntil with simple polling in teardown
qtbot.waitUntil processes Qt events while waiting, which can trigger
D-Bus operations that hang on Linux Python 3.12 CI. Use simple time-based
polling instead.
* Remove processEvents from teardown to avoid D-Bus hang
QCoreApplication.processEvents() in teardown triggers pending Qt events
which can include D-Bus operations that hang on Linux Python 3.12 CI.
* Add more debug to teardown signal disconnect
* Add debug around mock_db.close()
* Remove processEvents from load_window to avoid D-Bus hang
Replace QCoreApplication.processEvents() with time.sleep() to avoid
triggering D-Bus operations that hang on Linux Python 3.12 CI.
* Remove debug logging from CI hang investigation
Clean up debug print statements added during investigation of the
Python 3.12 Linux CI hanging issue. The actual fixes (skipping D-Bus
calls during tests, avoiding processEvents in fixtures) are preserved.
* Add debug timing to diagnose slow macOS CI tests
Adds timing instrumentation to identify the cause of ~20s delays
per test on GitHub Actions macOS runners:
- VortaApp.__init__: timing for each major initialization step
- qapp fixture: timing for session setup
- init_db fixture: timing for setup, teardown, and worker wait loop
- load_window: timing for MainWindow recreation
The debug output includes:
- Elapsed time for each operation
- Worker thread state (alive, current_job, process info)
- Iteration count for the worker wait loop
- Warning when wait loop times out
This will help identify if the delay is:
- In VortaApp/MainWindow initialization
- In the worker wait loop (BorgVersionJob not finishing)
- Somewhere else in the test infrastructure
* Skip CoreWLAN WiFi enumeration during tests to fix slow macOS CI
The root cause of ~20s delays per test on macOS CI runners was CoreWLAN
system calls hanging on headless runners without WiFi hardware.
Call chain causing the delay:
MainWindow.__init__ → ScheduleTab → NetworksPage → populate_wifi()
→ get_sorted_wifis() → get_network_status_monitor().get_known_wifis()
→ DarwinNetworkStatus._get_wifi_interface()
→ CWWiFiClient.sharedWiFiClient() ← HANGS ON HEADLESS CI
Fix: Skip system WiFi enumeration during tests by checking the
sys._called_from_test flag (already set in conftest.py). This is
consistent with how D-Bus is already skipped in scheduler.py.
Also removes debug timing code that was added to diagnose this issue.
* Add granular debug timing to MainWindow.__init__ for CI investigation
The previous CoreWLAN fix didn't resolve the 20s delay on macOS CI.
Adding timing around each major operation in MainWindow.__init__ to
identify the exact source of the delay:
- super().__init__
- setupUi
- setWindowIcon / LoadingButton
- Each tab creation (RepoTab, SourceTab, ArchiveTab, ScheduleTab, MiscTab, AboutTab)
- populate_profile_selector
- get_network_status_monitor().is_network_status_available()
- set_icons
* Skip psutil.process_iter() during tests to fix slow macOS CI
get_mount_points() iterates over all system processes which takes
~20 seconds on macOS CI runners. Since tests don't have actual borg
mount processes, skip this enumeration during test runs.
* Add debug timing inside ArchiveTab.__init__ to find slow line
* Add more granular debug timing inside ArchiveTab methods
* Add timing to final section of populate_from_profile
* Fix slow macOS CI tests by mocking DNS lookups
The root cause was socket.getaddrinfo() timing out (~10s each) when
format_archive_name() called _getfqdn() for archive name templates.
This happened twice per MainWindow creation, adding 20s per test.
Fix: Mock getaddrinfo in pytest_configure to return immediately for
AI_CANONNAME requests, avoiding DNS lookups during tests.
Also removes debug timing code and reverts unsuccessful earlier fixes.
* Fix DNS mock to handle all getaddrinfo calls, not just AI_CANONNAME
* Re-add CoreWLAN skip during tests to prevent hang on CI
* Fix CI hang: cache FQDN result instead of global DNS mock
The global getaddrinfo mock was breaking other networking code.
Instead, cache the FQDN result in _getfqdn() so the slow DNS lookup
only happens once per hostname, then returns cached value.
* Revert FQDN caching to isolate hang issue
* Patch _getfqdn specifically during tests to avoid slow DNS lookups
* Skip DNS lookup in _getfqdn during tests to fix CI slowness
Move the test check inside _getfqdn() itself instead of patching
from conftest.py. This avoids import timing issues that caused
test hangs.
* Add debug output to trace _getfqdn timing and flag state
* Add debug points to find actual hang location
DNS skip confirmed working. Adding debug at:
- MainWindow.__init__ end
- load_window() start/end
- init_db fixture yield point
* Add debug to test_prune_intervals to verify test starts
* Add detailed debug to test_prune_intervals
* Add debug to fixture teardown to find hang location
* Add debug to archive_env fixture
* Add debug at very start of init_db fixture
* Disable pytest-qt exception capture to fix macOS hang
pytest-qt's _process_events() hook causes hangs on macOS between tests.
Setting qt_no_exception_capture = true disables this behavior.
See: pytest-dev/pytest-qt#223
* Monkey-patch pytest-qt processEvents to prevent macOS hang
* Remove debug print statements after fixing macOS test hang
* refactor: Replace sys._called_from_test with pytest mocks
Move test-specific behavior out of production code into test fixtures.
Instead of checking sys._called_from_test in app code, mock the
problematic subsystems in tests/conftest.py:
- Mock QtDBus.QDBusConnection.systemBus to prevent D-Bus hangs
- Mock socket.getaddrinfo to prevent DNS lookup timeouts
- Mock get_network_status_monitor to prevent WiFi enumeration hangs
This keeps production code clean and follows Python testing best practices.
0 commit comments