Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .github/workflows/blitztext-linux-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ jobs:
- name: Compile-check (Syntax)
run: python -m compileall app

- name: Launch smoke test (App bootet offscreen)
env:
WHISPER_GUI_TESTS: "1"
run: python -m pytest tests/test_smoke_launch.py -v

- name: Run test suite (inkl. GUI offscreen)
env:
WHISPER_GUI_TESTS: "1"
Expand Down
49 changes: 49 additions & 0 deletions tests/test_smoke_launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""Launch-Smoke-Test: bootet die App offscreen noch und beendet sauber?

Zweck: bei jedem Push automatisch beantworten, ob sich die echte App noch
hochfahren laesst. Der Test konstruiert dieselbe ``BlitztextApp`` wie der
Produktiv-Einstiegspunkt ``main()`` (QApplication + Tray + Hauptfenster),
laesst einen echten Qt-Event-Loop kurz idlen und prueft, dass er sauber mit
Exit 0 zurueckkehrt.

Bewusst NICHT ueber ``main()``: ``main()`` ruft ``QApplication(sys.argv)`` neu
auf und wuerde im selben Prozess mit dem von der GUI-Suite wiederverwendeten
QApplication-Singleton kollidieren; ausserdem bricht ``_require_display_environment``
unter Offscreen (kein DISPLAY) ab. Wir spiegeln daher den Boot-Pfad in-process,
analog zu ``tests/test_state_machine.py`` (Fixture ``gui_app``).

Kein echter Hotkey/evdev-Thread (``stop_hotkey_worker`` vor dem Idle), kein
echtes Audio, keine echte Whisper/Piper-Nutzung. GUI-gated ueber
``WHISPER_GUI_TESTS=1`` (Display/Offscreen noetig).
"""
import os

import pytest

_GUI = os.environ.get("WHISPER_GUI_TESTS") == "1"
gui_only = pytest.mark.skipif(not _GUI, reason="benötigt WHISPER_GUI_TESTS=1 (Display)")


@gui_only
def test_app_boots_idles_and_exits_clean():
"""Echte App bootet offscreen, idlet kurz und beendet mit Exit 0."""
from PyQt6.QtCore import QTimer
from PyQt6.QtWidgets import QApplication

from app.blitztext_linux import BlitztextApp

qapp = QApplication.instance() or QApplication([])
app = BlitztextApp(qapp)
# Kein echter evdev-Thread waehrend des Idle-Loops (Pattern aus gui_app).
app.stop_hotkey_worker()
# Hauptfenster offscreen hochfahren -- exakt wie main().
app.show_main_window()

# Kurz idlen, dann deterministisch sauber beenden.
QTimer.singleShot(50, qapp.quit)
exit_code = qapp.exec()

assert exit_code == 0

# Idempotentes Cleanup, damit kein Thread in Folgetests nachhaengt.
app.stop_hotkey_worker()