Tests: Alt+F4 unabhängig von der Tastaturzustellung des Build-Rechners prüfen

Auf dem Runner gingen erzeugte Tastendrücke verloren (Tk stellt sie unter Windows nur dem Fenster
mit Tastaturfokus zu); der Watchdog brach dann ab und es sah aus, als hätte sich das Programm
beendet. Handler wird jetzt direkt aufgerufen, die Bindung separat geprüft; Watchdog-Abbrüche
werden als Zeitüberschreitung gemeldet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-11-02 11:43:29 +01:00
1 parent 86192c853d
commit 2b2d5e8580
1 file changed
+29 -7
+29 -7
View File
@@ -47,6 +47,7 @@ class Lauf:
raise
pytest.skip(f"kein Bildschirm: {exc}")
self.fehler: list[str] = []
self.watchdog = False # True = der TEST hat wegen Zeitüberschreitung abgebrochen
from provtool.gui import app as A
self.app = A.App(self.root)
echt = self.root.report_callback_exception
@@ -62,6 +63,13 @@ class Lauf:
self.root.report_callback_exception = melden
# ---------------------------------------------------------------- Zustand
def lebt_sonst(self, text: str) -> str:
"""Fehlertext für „Programm ist zu“, der Watchdog-Abbrüche klar unterscheidet."""
if self.watchdog:
return "Zeitüberschreitung – der Test hat abgebrochen (nicht das Programm hat sich beendet):\n" \
+ "\n".join(self.fehler)
return text
@property
def lebt(self) -> bool:
try:
@@ -95,6 +103,7 @@ class Lauf:
d.destroy()
def _notaus(self):
self.watchdog = True
for d in reversed(self.dialoge()):
try:
d.destroy()
@@ -219,11 +228,11 @@ def test_alt_f4_im_assistent_fragt_und_schliesst_nur_assistent(home):
d.destroy()
lauf.ablauf([
(_assistent_offen(lauf), lambda: lauf.dialog(Einrichtungsassistent).event_generate("<Alt-F4>"), "Alt+F4"),
(_assistent_offen(lauf), lambda: lauf.app.rahmen.alt_f4(lauf.dialog(Einrichtungsassistent)), "Alt+F4"),
(lambda: rueckfrage() is not None, ja_klicken, "Rückfrage mit Ja beantworten"),
(lambda: lauf.dialog(Einrichtungsassistent) is None, lambda: None, "Assistent ist zu"),
])
assert lauf.lebt, "Programm darf nicht beendet werden"
assert lauf.lebt, lauf.lebt_sonst("Programm darf nicht beendet werden")
assert not lauf.uebrig, lauf.uebrig
assert lauf.app.settings.get("assistent_erledigt") is True
lauf.pruefen()
@@ -252,12 +261,15 @@ def test_alt_f4_im_dialog_schliesst_nur_den_dialog(lauf_mit_daten, monkeypatch):
lauf.ablauf([
(IMMER, lambda: InfoDialog(lauf.root).zeigen(), "Info öffnen"),
# Handler direkt mit dem Dialog als Empfänger aufrufen: Erzeugte Tastendrücke stellt Tk unter
# Windows nur dem Fenster mit Tastaturfokus zu – auf dem Build-Rechner gingen sie verloren.
# Dass Alt+F4 an diesen Handler gebunden ist, prüft test_alt_f4_ist_gebunden.
(lambda: lauf.dialog(InfoDialog) is not None,
lambda: lauf.dialog(InfoDialog).event_generate("<Alt-F4>"), "Alt+F4 im Dialog"),
lambda: lauf.app.rahmen.alt_f4(lauf.dialog(InfoDialog)), "Alt+F4 im Dialog"),
(lambda: lauf.dialog(InfoDialog) is None, lambda: None, "Dialog geschlossen"),
], sekunden=8)
diagnose = "\n---\n".join(protokoll) + "\nFehler:\n" + "\n".join(lauf.fehler)
assert lauf.lebt, "Alt+F4 im Dialog darf nicht das ganze Programm beenden\n" + diagnose
assert lauf.lebt, lauf.lebt_sonst("Alt+F4 im Dialog darf nicht das ganze Programm beenden\n" + diagnose)
assert not lauf.uebrig, f"{lauf.uebrig}\n{diagnose}"
lauf.pruefen()
@@ -315,6 +327,16 @@ def test_schliessen_waehrend_rundgang(lauf_mit_daten):
lauf.pruefen()
def test_alt_f4_ist_gebunden(lauf_mit_daten):
"""Alt+F4 muss im Win95-Rahmen an den eigenen Handler gebunden sein (für alle Fenster)."""
lauf = lauf_mit_daten
if not lauf.app.rahmen.klassisch:
pytest.skip("nur im Win95-Rahmen")
skript = lauf.root.bind_all("<Alt-F4>")
assert skript, "Alt+F4 ist nicht gebunden"
lauf.pruefen()
def test_alt_f4_bevor_die_sperre_steht(lauf_mit_daten, monkeypatch):
"""Erzwingt den Zustand vom langsamen Build-Rechner: Dialog ist offen, aber Tk-Sperre und
Zeichnen sind noch nicht fertig. Alt+F4 muss trotzdem nur den Dialog schließen."""
@@ -330,7 +352,7 @@ def test_alt_f4_bevor_die_sperre_steht(lauf_mit_daten, monkeypatch):
"Alt+F4 (Fokus noch beim Hauptfenster)"),
(lambda: lauf.dialog(InfoDialog) is None, lambda: None, "Dialog geschlossen"),
], sekunden=8)
assert lauf.lebt, "Alt+F4 darf bei offenem Dialog nicht das ganze Programm beenden"
assert lauf.lebt, lauf.lebt_sonst("Alt+F4 darf bei offenem Dialog nicht das ganze Programm beenden")
assert not lauf.uebrig, lauf.uebrig
lauf.pruefen()
@@ -341,10 +363,10 @@ def test_alt_f4_im_rundgang_beendet_nur_den_rundgang(lauf_mit_daten):
lauf.ablauf([
(IMMER, lauf.app.rundgang, "Rundgang starten"),
(lambda: rg() is not None and rg().blase is not None,
lambda: rg().blase.event_generate("<Alt-F4>"), "Alt+F4"),
lambda: lauf.app.rahmen.alt_f4(rg().blase), "Alt+F4"),
(lambda: rg().blase is None and not rg().rahmen, lambda: None, "Rundgang samt Rahmen weg"),
], sekunden=8)
assert lauf.lebt, "Alt+F4 im Rundgang darf nicht das Programm beenden"
assert lauf.lebt, lauf.lebt_sonst("Alt+F4 im Rundgang darf nicht das Programm beenden")
assert not lauf.uebrig, lauf.uebrig
lauf.pruefen()