„Getestet“ ist ohne Nachweisstufe zu ungenau
In gewachsenen Steuerungsprojekten bedeutet Testen häufig: übersetzen, herunterladen, Maschine vorsichtig starten und beobachten. Das ist verständlich, wenn Logik und Hardware eng gekoppelt sind. Es macht aber jede kleine Änderung von Anlagenzugang, Personal, Material und einem sicheren Testfenster abhängig. Außerdem werden Fehler erst dort sichtbar, wo ihre Auswirkungen am teuersten oder riskantesten sein können.
Bessere Testbarkeit beginnt nicht mit einem großen Simulationsprojekt. Sie beginnt mit einer präziseren Sprache. Vier Nachweisstufen beantworten vier unterschiedliche Fragen:
- Quellcodeanalyse: Ist die Logik strukturell verstanden und sind Abhängigkeiten sowie auffällige Risiken sichtbar?
- Reproduzierbarer Build: Lässt sich der referenzierte Stand mit einer definierten Werkzeugkette wieder erzeugen?
- Logiktest oder DryRun: Reagiert die Software unter kontrollierten, modellierten Bedingungen wie erwartet?
- Reale Maschinenvalidierung: Funktioniert das integrierte System mit echter Hardware, Kommunikation, Mechanik und Bedienung im vorgesehenen Einsatz?
Je früher eine Prüfung stattfinden kann, desto enger lässt sich eine Abweichung meist eingrenzen. Je näher die Prüfung an der realen Maschine liegt, desto mehr reale Wechselwirkungen erfasst sie.
Stufe 1: Quellcodeanalyse schafft ein prüfbares Modell
Eine statische Analyse führt noch keinen einzigen Maschinenzyklus aus. Trotzdem ist sie der Ausgangspunkt für sinnvolle Tests. Sie zeigt, wo Zustände entstehen, welche Signale sie verändern und welche Teile des Programms überhaupt isolierbar sind.
Signal- und Aufrufwege statt nur Bausteinlisten
Für eine relevante Funktion wird der Weg vom Eingang bis zum Ausgang verfolgt: physisches Signal oder Kommunikationswert, Eingangskonditionierung, Betriebsart, Freigaben, Ablaufsteuerung, Befehlsbildung und schließlich Hardwareausgabe. Parallel wird erfasst, welche Bausteine aus welchen Tasks aufgerufen werden und welche globalen Daten den Weg beeinflussen.
Dabei fallen typische Testhindernisse auf:
- direkte Hardwarezugriffe tief in der Ablaufsteuerung,
- mehrere Schreibstellen für dasselbe Kommando oder denselben Zustand,
- implizite Abhängigkeiten von Aufrufreihenfolge oder Zykluszeit,
- Timer und Flankenerkennung ohne kontrollierbare Zeitbasis,
- globale Betriebsarten, die viele scheinbar unabhängige Bausteine verändern,
- und Fehlerbehandlung, die nur im Normalablauf zurückgesetzt wird.
Zustandsautomaten und Invarianten benennen
Ein Test wird stärker, wenn er nicht nur einzelne Ausgangswerte prüft, sondern Regeln, die immer gelten sollen. Solche Invarianten können beispielsweise lauten: Ein Bewegungsbefehl darf nur in der passenden Betriebsart entstehen. Zwei gegensätzliche Kommandos dürfen nie gleichzeitig aktiv sein. Ein abgebrochener Ablauf muss einen definierten Rücksetzpfad haben. Eine Quittierung darf die Ursache eines weiterhin anstehenden Fehlers nicht verdecken.
Welche Regeln fachlich richtig und sicherheitsrelevant sind, muss am konkreten System geklärt werden. Die Codeanalyse liefert dafür Kandidaten und offene Fragen. Sie ersetzt weder die Risikobeurteilung noch eine reale Funktionsprüfung.
Stufe 2: Ein reproduzierbarer Build ist selbst ein Test
Wenn nur ein bestimmter Entwicklungsrechner ein Projekt übersetzen kann, ist jede weitere Teststufe auf einem unsicheren Fundament aufgebaut. Ein reproduzierbarer Build prüft, ob der Quellstand vollständig und seine Abhängigkeiten kontrolliert sind.
Was zur Build-Definition gehört
- eindeutige Revision oder unveränderlich gesichertes Projektarchiv,
- Entwicklungsumgebung samt Service-Pack beziehungsweise Patchstand,
- Zielsystem-, Geräte- und Laufzeitdefinitionen,
- Bibliotheken mit aufgelösten Versionen statt zufälliger lokaler Auswahl,
- Build-Optionen, bedingte Übersetzung und Variantenparameter,
- ein dokumentierter Weg vom Quellstand zum Download- oder Bootartefakt,
- sowie eine Behandlung von Warnungen, die nicht einfach als bekannte Geräuschkulisse gilt.
Der Wiederholungsversuch sollte aus einer kontrollierten, möglichst sauberen Umgebung erfolgen. Entscheidend ist, dass ein zweiter Bearbeiter oder eine neu aufgesetzte Build-Station denselben Weg nachvollziehen kann. Wo Werkzeuge keinen bitidentischen Vergleich ermöglichen, werden zumindest Eingänge, Versionen, Meldungen und erzeugte Artefakte eindeutig protokolliert.
Stufe 3a: Logiktests für kleine, deterministische Einheiten
Isolierte Tests eignen sich besonders für Bausteine, deren Ein- und Ausgänge fachlich klar sind: Skalierungen, Grenzwertüberwachung, Auswahlregeln, Freigabelogik, Protokollzustände oder einzelne Schritte eines Zustandsautomaten. Der Test setzt definierte Eingangswerte, führt eine kontrollierte Anzahl Zyklen aus und vergleicht beobachtete mit erwarteten Ergebnissen.
Ein Testfall braucht mehr als Eingang und Sollwert
Für jeden Fall sollten mindestens Ausgangszustand, Eingangsfolge, Zeitbezug, erwartete Zwischenzustände, Endzustand und relevante Diagnosewerte feststehen. Bei zyklischer Logik ist außerdem wichtig, wann ein Wert gesetzt wird: vor dem Aufruf, zwischen zwei Zyklen oder nach einem Zustandswechsel.
Ein generisches Beispiel ist eine Schrittfolge mit Anforderung, Freigabe und Rückmeldung:
- Im Grundzustand darf ohne Anforderung kein Kommando entstehen.
- Mit Anforderung, aber ohne Freigabe bleibt die Folge gesperrt und meldet den Grund.
- Mit Freigabe entsteht das Kommando, der Zustand wechselt jedoch erst bei Rückmeldung.
- Bleibt die Rückmeldung aus, muss nach definierter Zeit eine nachvollziehbare Reaktion folgen.
- Nach Abbruch wird das Kommando entfernt und ein definierter Rücksetzweg verlangt.
Dieses Muster prüft fachliche Logik. Ob das Kommando einen realen Aktor sicher ansteuern darf und ob Zeitgrenzen zum Prozess passen, bleibt eine Frage des konkreten Systems.
Zeit kontrollierbar machen
Echte Wartezeiten machen Tests langsam und nicht deterministisch. Wo die Architektur es zulässt, wird Zeit deshalb über einen kontrollierbaren Takt oder eine klar gekapselte Zeitquelle eingebracht. Dann kann ein Test gezielt „50 Millisekunden später“ oder „nach Ablauf der Überwachungszeit“ ausführen, ohne von Rechnerlast oder Wandzeit abzuhängen.
In einem Legacy-Projekt lässt sich diese Kapselung nicht immer sofort einführen. Dann können zunächst kurze Sequenztests mit dokumentierter Zykluszahl helfen. Wichtig ist, keine Scheingenauigkeit zu behaupten: Ein simulierter Zyklus prüft die Programmlogik, nicht den Jitter einer realen Laufzeit.
Stufe 3b: DryRun für zusammenhängende Abläufe
Ein DryRun führt größere Teile der echten Steuerungslogik aus, trennt aber die Befehlsbildung von der realen Hardwareausgabe. Eingänge kommen aus einem Testtreiber oder einem begrenzten Anlagenmodell. Ausgänge werden aufgezeichnet, plausibilisiert oder zurück in das Modell geführt, ohne die realen Aktoren anzusteuern.
Die Hardwaregrenze muss eindeutig sein
Der DryRun darf nicht auf verstreuten Sonderfällen beruhen, die einzelne Ausgänge zufällig unterdrücken. Robuster ist eine erkennbare Signalgrenze:
- physische und kommunikative Eingänge werden in logische Maschinensignale übersetzt,
- die Maschinenlogik arbeitet nur mit diesen logischen Signalen,
- logische Befehle werden zentral in physische Ausgänge oder Protokolltelegramme übersetzt,
- und der Testbetrieb ersetzt ausschließlich die Ein- und Ausgabeseite.
Ist diese Trennung im Bestand nicht vorhanden, kann sie schrittweise für die zu ändernde Funktion eingeführt werden. Ein kompletter Architekturumbau nur für einen einzelnen Test wäre häufig unverhältnismäßig.
Was ein DryRun sinnvoll abdecken kann
Geeignet sind Varianten und Fehlerpfade, die an der Maschine teuer oder schwer wiederholbar wären: fehlende Rückmeldungen, falsche Reihenfolgen, Kommunikationsunterbrechungen, Bedienabbrüche, Wiederanlauf nach einem definierten Zustand oder Grenzwerte an Parameterschnittstellen. Neben Endergebnissen sollten Zustandswechsel, Kommandos und Diagnoseursachen als Trace aufgezeichnet werden.
Das Anlagenmodell muss dabei nur so detailliert sein wie die Frage. Für einen Handshake-Test kann ein Zustandsmodell genügen; für Regelungs- oder hochdynamische Vorgänge wäre ein deutlich genaueres Modell nötig. Ein zu grobes Modell darf nicht als Beweis für reale Dynamik verwendet werden.
Testbetrieb gegen unbeabsichtigte Aktivierung absichern
Ein DryRun-Modus ist selbst eine Änderung am Steuerungssystem. Seine Aktivierung, Sichtbarkeit und Auswirkung müssen eindeutig sein. Insbesondere darf ein Testpfad nicht unbemerkt im Produktionsbetrieb aktiv werden oder Schutzfunktionen umgehen. Ob und wie ein solcher Modus zulässig ist, wird für die konkrete Maschine abgestimmt. Softwareseitige Kennzeichnungen allein ersetzen keine organisatorischen und technischen Schutzmaßnahmen.
Stufe 4: Reale Maschinenvalidierung bleibt unverzichtbar
Logiktests und DryRun reduzieren den Suchraum. Sie erfassen aber keine Kontaktprellung, elektrische Störung, reale Buslast, Sensorstreuung, mechanische Toleranz, Antriebsdynamik oder überraschende Bedienhandlung. Auch die tatsächliche Zyklus- und Reaktionszeit entsteht erst aus Laufzeit, Hardware und angeschlossenen Teilnehmern.
Die reale Prüfung sollte deshalb aus den früheren Stufen abgeleitet werden, aber einen eigenen Plan haben:
- Welche Revision und welches Artefakt werden geladen?
- Welche Sicherung und welcher Rückweg sind vorbereitet?
- Welche Betriebsart und sichere Ausgangsstellung werden benötigt?
- Wer darf den Test starten, beobachten und abbrechen?
- Welche Fälle sind im verfügbaren Zeitfenster zulässig?
- Welche Messwerte, Ereignisse und Bedienhandlungen werden protokolliert?
- Welche Abweichung beendet den Versuch sofort?
Die erforderliche Tiefe richtet sich nach Funktion, Maschine und Risiko. Ein fachlicher Softwaretest ist keine Sicherheitsvalidierung und keine Produktionsfreigabe. Zuständigkeiten und Freigaben müssen außerhalb des Testcodes geklärt sein.
Eine schlanke Nachweiskette für Änderungen
Testdokumentation muss nicht aus einem großen, nachträglich geschriebenen Bericht bestehen. Für eine einzelne Änderung kann eine kompakte, durchgängige Kette genügen:
- Anforderung: Welches beobachtbare Verhalten soll sich ändern – und welches ausdrücklich nicht?
- Revision: Welcher Quellstand und welche Konfiguration bilden die Grundlage?
- Änderung: Welche Bausteine, Signale und Abhängigkeiten sind betroffen?
- Build: Mit welcher Werkzeugkette wurde welches Artefakt erzeugt?
- Frühe Tests: Welche Logik- und DryRun-Fälle wurden ausgeführt, mit welchem Ergebnis und welcher Aussagegrenze?
- Maschinenprüfung: Welche realen Fälle wurden durch wen unter welchen Bedingungen geprüft?
- Restpunkte: Was blieb ungetestet, wurde verworfen oder braucht Beobachtung im weiteren Betrieb?
So bleibt auch Monate später nachvollziehbar, ob „getestet“ einen statischen Review, einen simulierten Ablauf oder eine reale Maschinenprüfung bezeichnete.
Wo KI-gestützte Werkzeuge helfen – und wo nicht
KI-gestützte Werkzeuge können Quellstrukturen erfassen, Testfälle vorschlagen, Dokumentationsentwürfe erzeugen oder große Mengen an Traces vorsortieren. Das kann die Bearbeitung beschleunigen. Der Umgang mit vertraulichem Quellcode und Maschinendaten muss vor dem Einsatz ausdrücklich geregelt sein.
Ein generierter Test ist nicht automatisch fachlich richtig. Technische Führung, Review, Auswahl der erwarteten Ergebnisse und Bewertung verbleiben bei Fabian Egeberg. Vor allem kann ein Werkzeug nicht aus dem Code allein ableiten, ob eine Maschinenreaktion im realen Prozess sicher und beabsichtigt ist. Diese Bewertung und die reale Validierung bleiben eigenständige Nachweisstufen.
Pragmatisch anfangen
Nicht jeder Bestand braucht sofort ein vollständiges Testframework. Ein sinnvoller Einstieg ist häufig eine konkrete, wiederkehrende Änderung: Buildweg sichern, betroffenen Signalpfad erfassen, zwei oder drei kritische Invarianten benennen und den ersten kontrollierten Sequenztest aufbauen. Danach zeigt sich, welche Kapselung auch für weitere Funktionen Nutzen bringt.
Das Ziel ist nicht, die reale Maschine aus dem Prüfprozess zu entfernen. Das Ziel ist, sie nicht länger als einzige Debugging-Umgebung zu benötigen – und vor dem ersten realen Versuch bereits möglichst viele klar begrenzte Fragen beantwortet zu haben.