Commit a764161
committed
fix(tests): collect leaked QObjects between tests to end Py3.12 isolation flake
Ursache:
Mehrere GUI-Tests (test_smoke_launch, test_tray_preset_menu,
test_settings_dialog, gui_app in test_state_machine) erzeugen BlitztextApp
(selbst ein QObject) samt HotkeyWorker, QThread und Fenstern ohne Qt-Parent
und lassen die Python-Referenz am Testende fallen. Diese Objekte haengen in
Referenzzyklen (Signal/Slot-Verbindungen zeigen auf self), sodass der Refcount
sie nicht abraeumt -- erst Pythons zyklischer GC loescht die C++-Objekte, zu
nichtdeterministischem Zeitpunkt. Auf CPython 3.12 (CI-Matrix) faellt dieser
GC-Lauf reproduzierbar mitten in HotkeyWorker.run() eines Folgetests; sip
meldet dann den laufenden Worker als geloescht:
RuntimeError: wrapped C/C++ object of type HotkeyWorker has been deleted
(app/hotkey_service.py:307, self.workflow_triggered.emit)
Betroffen: tests/test_state_machine.py::TestLeftAltEvents::
test_leftalt_keydown_triggers_toggle.
Fix:
Autouse-Fixture in tests/conftest.py ruft nach JEDEM Test gc.collect(). Der
Abbau der geleakten Zyklen wird damit deterministisch an der Testgrenze
erzwungen -- waehrend kein Worker laeuft. Im Folgetest bleibt fuer den GC
nichts mehr einzusammeln, das mit einem laufenden run() kollidieren koennte.
Reiner Test-Fix, kein Produktivcode.
Bewusst NUR gc.collect(): eine erste, aggressivere Variante mit
processEvents()+sendPostedEvents(DeferredDelete) loeschte noch von Tests
referenzierte Widgets vorzeitig und provozierte C++-Doppel-Frees
(Fatal Python error: Aborted). gc.collect() bricht nur echte, unerreichbare
Zyklen auf und ist nebenwirkungsfrei.
Verifikation (Py3.12-venv wie CI, QT_QPA_PLATFORM=offscreen, WHISPER_GUI_TESTS=1):
- Einzeltest, test_state_machine.py, volle Suite: gruen (494 passed)
- Zusaetzlich Py3.14: gruen; Non-GUI-Default: 424 passed / 70 skipped
- Leak-Messung: geleakte BlitztextApp zwischen Tests 7 -> 2 (Peak)
- compileall app + secret-scan (CI-Muster): sauber
Risiken:
gc.collect() nach jedem Test erhoeht die Suite-Laufzeit der Offscreen-GUI-
Suite (~10s -> ~20s bei 494 Tests). Bewusst zugunsten deterministischer
Isolation akzeptiert. Keine Testdeaktivierung, kein skip/xfail/retry.
Rollback:
git revert <diese Commit-SHA> bzw. Entfernen der Fixture
_collect_leaked_qobjects aus tests/conftest.py stellt den alten Stand her.1 parent 646f471 commit a764161
1 file changed
Lines changed: 35 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
13 | 16 | | |
14 | 17 | | |
15 | 18 | | |
| 19 | + | |
16 | 20 | | |
17 | 21 | | |
18 | 22 | | |
| |||
23 | 27 | | |
24 | 28 | | |
25 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
0 commit comments