Testen und Inbetriebnehmen

mpylab-Anwendungen verbinden numerische Auswertung, lange Zustandsabläufe und reale Hardware. Keine einzelne Testart deckt alle drei Bereiche ausreichend ab. Neue Funktionen werden deshalb in mehreren Stufen abgesichert.

1. Reine Logik

Algorithmen, Einheitenumrechnungen, Parser und Datenstrukturen werden ohne Gerätegraph getestet. Diese Tests sind schnell und prüfen insbesondere:

  • Grenzwerte und Bereichsübergänge;

  • Einheiten, Unsicherheiten und komplexe Größen;

  • leere, unvollständige und nicht endliche Eingaben;

  • deterministische Serialisierung und Rückgabestrukturen.

Mocks sind hier sinnvoll, wenn ein einzelner Fehlerzustand gezielt erzeugt werden muss. Sie sollen nicht die öffentliche API eines ganzen Geräts nachbilden.

2. Geräteschnittstelle

Jede Gerätebasisklasse definiert gemeinsame Anforderungen an ihre öffentliche Schnittstelle. Ein spezifischer Treiber wird gegen diese Anforderungen getestet: Statuscodes, Quantities, Triggerreihenfolge, Kanaltrennung, Zeitüberschreitung und Quit.

Die geprüften Regeln sind unter Gemeinsames Gerätetreiber-Verhalten zusammengefasst.

Protokolltests verwenden eine kontrollierte Kommunikationsklasse und prüfen die tatsächlich gesendeten Befehle sowie vollständig gelesene Antworten. Sie benötigen keine Laborhardware.

3. Virtuelle Konfiguration

Virtuelle Treiber und echte DOT-/INI-Dateien prüfen das Zusammenspiel von Konfiguration, MGraph und Messklasse. Ein Konfigurationstest soll mindestens:

  1. den Graph laden;

  2. alle Geräte erzeugen;

  3. die Geräte initialisieren;

  4. Conditions für repräsentative Werte auswerten;

  5. RF-Off und Quit ausführen.

Damit werden falsche Treibernamen, Kanäle, Suchpfade und Gerätemappings gefunden, die ein isolierter Unit-Test nicht sieht.

4. Virtueller End-to-End-Lauf

Ein kurzer Lauf mit wenigen Frequenzen und Pegeln verwendet das reguläre Skript. Er prüft:

  • Mess- und Auswertedaten im finalen Pickle;

  • Roh- und Ausgabedateien;

  • Log und Preflight;

  • Historienverweise auf vorbereitende Messungen;

  • Reportmodule, sofern vorhanden.

Der Test verwendet temporäre Ausgabeverzeichnisse. Log- oder Pickle-Dateien dürfen nicht im Projektwurzelverzeichnis zurückbleiben.

5. Autosave und Wiederanlauf

Ein Resume-Test unterbricht den virtuellen Lauf nach einem definierten Punkt, lädt das Autosave über load_pickle_compat und führt dieselbe Messroutine erneut aus. Er weist nach, dass:

  • vollständige Punkte nicht erneut gemessen werden;

  • ein unvollständiger Punkt sauber wiederholt wird;

  • die Historie erhalten bleibt;

  • das finale Ergebnis dem nicht unterbrochenen Referenzlauf entspricht;

  • das Autosave erst nach erfolgreichem Abschluss entfernt wird.

6. Safety- und Negativtests

Schutzfunktionen werden gezielt ausgelöst. Dazu gehören fehlende Graphpfade, mehrdeutige Conditions, MAXIN, AmplifierProtect, nicht erreichbare Leveling-Ziele, Bedienerabbruch und Fehler während der Gerätekommunikation.

Erwartetes Verhalten ist nicht immer ein Programmabbruch. Ein Leveler kann an einer Schutzgrenze stoppen und den begrenzten Zustand protokollieren. RF-Off muss dennoch ausgeführt werden.

7. Qt-Tests

Headless-Tests verwenden:

QT_QPA_PLATFORM=offscreen \
    python -m pytest test/test_qt_ui_adapter.py

Sie prüfen Thread-Lebensdauer, inkrementellen Fortschritt, Stop, Fehleranzeige und das Schließen während einer laufenden Operation. Zeitkritische Tests warten auf Signale oder Zustände statt auf unnötig lange feste Pausen.

8. Gestufter Hardwaretest

Ein Hardwaretest beginnt nicht mit dem vollständigen Messbereich:

  1. Preflight ohne HF.

  2. Geräte einzeln initialisieren und identifizieren.

  3. RF-Off und Grenzkanäle prüfen.

  4. Eine Frequenz und einen sicheren Pegel messen.

  5. Kleinen Frequenzbereich oder wenige Punkte ausführen.

  6. Autosave und Wiederanlauf praktisch prüfen.

  7. Erst danach den vollständigen Ablauf freigeben.

Die Templates unter script/conf enthalten für kritische TEM-Abläufe eine HARDWARE_TEST.md. Lokale Besonderheiten und Ergebnisse des ersten Inbetriebnahmelaufs werden dort oder in der Konfigurationsdokumentation festgehalten.

Lokale Tests und CI

Der vollständige lokale Testlauf entspricht dem Kern der Pipeline:

python -m pip install -e ".[dev]"
python -m coverage run -m pytest test
python -m coverage report

Die Dokumentation wird separat und mit Warnungen als Fehler gebaut:

sphinx-build -W --keep-going -E -a \
    -b html docs/next/source docs/next/build/html

Coverage zeigt nicht, ob ein Messablauf fachlich richtig geprüft ist. Insbesondere Safety, Resume und Rückführbarkeit benötigen explizite Verhaltensassertionen.