Mehrfachtestbaustein implementieren
Um viele zusammengehörige Testfälle in nur einem Testbaustein zu realisieren, können Sie das Pragma {attribute 'test' := 'multitest'}
verwenden: Sie dekorieren einen Testbaustein mit ETrigA
-Verhalten mit diesem Pragma. Bei der Protokollierung während des Testablaufs werden dann zusätzliche Informationen übermittelt. So wird beispielsweise das Testergebnis für jeden einzelnen Testfall übermittelt und protokolliert. Dafür werden weitere Ein- und Ausgänge benötigt.
Grundgerüst für den Testfall erstellen
Ein Testfall ist ein Funktionsbaustein, der einem bestimmten Schema folgt (Schnittstellenkonvention). Um das Einhalten des Schemas zu erleichtern, empfehlen wir, den Wizard zu nutzen. Wenn Sie einen Testfall manuell erstellen, sollte er immer von TM.BaseMultiTest
ableiten. (Obsolete Testbaustein-Implementierungen).
Fügen Sie den Testfall-Funktionsbaustein unter einer Applikation oder im POU-Pool hinzu. Wählen Sie dazu den Befehl Objekt hinzufügen → Unittest aus den Kontextmenü.
Der Dialog Unittest hinzufügen öffnet sich.
Geben Sie folgende Parameter ein:
Name der POU:
TestCase_1
Typ: Extend TM.BaseMultiTest
Optionale Methoden hinzufügen
Implementierungsvorlagen hinzufügen
Erklärende Kommentare hinzufügen
Testfallkategorie:
BasicTests
Bestätigen Sie den Dialog mit Hinzufügen und speichern Sie das Projekt.
Ein neuer Funktionsbaustein mit den Methoden
Execute
,Setup
,Teardown
undAbort
entsteht.
Für weitere Informationen siehe: Unittest hinzufügen
Testlogik implementieren
Deklarieren Sie eine Instanz des Prüflings im Deklarationsteil des Testbaustein. Das Beispiel testet einen CTU-Standardbaustein.
{attribute 'test':='multitest'} {attribute 'testcasetimeout':='15000'} FUNCTION_BLOCK CTU_TestCases EXTENDS TM.BaseMultiTest VAR_INPUT END_VAR VAR_OUTPUT END_VAR VAR counter : CTU; // testee instance cycleCounter : INT; // independant test control variable END_VAR
Initialisieren Sie den Prüfling im Implementierungsteil der Methode
prvStart
. Das Beispiel initialisiert den CTU per Reset und initialisiert gegebenenfalls Variablen, die für den Testablauf benötigt werden. DieprvStart
-Methode wird einmalig vorprvCyclicAction
aufgerufen.SUPER^.prvStart(); // mandatory - don't change // Initialize the testee counter(CU:=FALSE, RESET:=TRUE); // reset the counter; note: initialization per test case must be performed in prvCyclicAction // Initialize test control variable for first test case cycleCounter := 0;
Rufen Sie den Prüfling auf und prüfen Sie dessen Ergebnisses in der Methode
prvCyclicAction
. Die MethodeprvCyclicAction
wird solange aufgerufen, bisxDone
aufTRUE
gesetzt wurde. Der Prüfling kann somit je Testfall über mehrere SPS-Zyklen aufgerufen werden. Das folgende Beispiel implementiert nur einen Testfall (CASE 0
), weitere Testfälle können jedoch nach diesem Schema einfach hinzugefügt werden.SUPER^.prvCyclicAction(); // mandatory - dont' change CASE diTestCaseIndex OF 0: // test case #0; add test cases as new CASEs IF xGetTestInfo THEN // initializate test case // define mandatory test case information wsTestCaseName := "Count from 0 to 5"; wsTestCaseCategories := "CTU"; diTestCaseTimeout := 500; xDone := TRUE; // signal test case initialization done ELSE IF (cycleCounter = 0) THEN // prepare test case counter(CU:=FALSE, RESET:=TRUE, PV:=5); // stimulate testee as long as we expect: 5 rising edges to count to 5 equals minimum 10 cycles ELSIF (cycleCounter < 10) THEN // check: counter limit not reached yet TM.Assert_Bool_IsFalse(THIS^, counter.Q, "Counter signaled limit reached prematurely"); TM.Assert_Word_Less(THIS^, 5, counter.CV, "Counter reached limit unexpectedly"); counter(CU:= (NOT counter.CU), RESET:=FALSE); // Trigger counter with rising edges xDone := FALSE; // signal test still running ELSE // check: counter reached limit TM.Assert_Bool_IsTrue(THIS^, counter.Q, "Counter did not signal limit reached"); TM.Assert_Word_Equal(THIS^, 5, counter.CV, "Counter did not reach limit"); xDone := TRUE; // mandatory: signal test completed END_IF IF xDone OR xError THEN cycleCounter := 0; // clean up for next test case ELSE cycleCounter := cycleCounter + 1; // count cycles END_IF END_IF ELSE IF diTestCaseIndex < 0 THEN // mandatory, signal number of test cases, if called with (diTestCaseIndex < 0) diTestCaseCount := 1; xDone := TRUE; ELSE // mandatory, don't remove: fail for invalid test case index wsInfo := "Invalid test case index"; iError := 2; END_IF END_CASE
Eine Deinitialisierung des Tests könnte in der Methode
prvResetOutputs
stattfinden, wird aber in diesem Beispiel nicht benötigt. Löschen Sie die Methode.Es muss kein besonderer Code ausgeführt werden, wenn der Test in einen Timeout läuft. Löschen Sie die Methode
prvAbort
.
Testelement IEC-Unittest konfigurieren
Geben Sie im Titel einen Testfallnamen ein.
Beispiel:
N_001_Test
Bei Testausführung erscheint der Titel als Testfallname.
Geben Sie in Timeout Gerät lesen (ms) eine Zeit an. Beispiel:
5000
Hinweis: Bei jedem Testfall wird mindestens beim Auslesen von Teststatus und Testergebnis gewartet. Außerdem wird beim Einloggen gewartet, wenn der Applikationsstatus ausgelesen wird.
Beim Auslesen von Variablen wird gewartet, bis der Timout abgelaufen ist, erst dann wird gelesen.
Geben Sie in Erneute Login-Versuche an, wie oft maximal versucht wird den Onlinebetrieb herzustellen. Beispiel:
3
Klicken Sie links oben in der Tabelle Ausgewählte Kategorien.
Ein Eingabefeld erscheint.
Geben Sie alle Kategorien ein, die in diesem Testfall aufgerufen werden.
Beispiel:
BasicTests
Alle Test-Funktionsbausteine, die mit dem Attribut
'testcategory' := 'BasicTests'
dekoriert sind, werden in diesem Testfall aufgerufen.
Testskript ausführen
Voraussetzung: Die Testumgebung ist vorbereitet. Das Testprojekt ist im CODESYS Development System geöffnet und die Geräte- und Kommunikationseinstellungen sind konfiguriert. Diese notwendigen Anweisungen werden durch einen vorbereitenden Testfall im Testskript vorgenommen.
Der Inhalt des Ordners Generated Unit Tests wird gelöscht, um die generierten Bausteine eines vorherigen IEC-Unittests zu entfernen.
Das Projekt und die Bibliotheken zum Testen werden nach Testtabellen durchsucht. Dann werden die Funktionsbausteine für die Ausführung der Testtabellen im Ordner Generated Unit Tests generiert.
Das Projekt und die Bibliotheken, die unter Bibliotheken zum Testen aufgelistet sind, werden durchsucht nach Funktionsbausteinen und Programmen, die als Test markiert sind.
Dann werden unter den ermittelten Programmen und Funktionsbausteinen diejenigen entfernt, die über die Testkategorien oder den Namen ausgeschlossen sind.
Die verbleibenden Programme und Funktionsbausteine werden für den Test berücksichtigt.
Ein Backup der ursprünglichen Applikation wird erstellt.
Die Testfälle werden als IEC-Code in
PLC_PRG
eingefügt. Die (in der Deklaration und in der Implementierung) hinzugefügten Codezeilen werden mitGenerated by IEC Unit Test
markiert.Wenn die Applikation zu groß für die Steuerung ist, werden automatisch die Tests auf mehrere Applikationen aufgeteilt. Eine oder mehrere ablauffähige Applikationen werden generiert.
Der Test mit der erzeugten Applikation / den erzeugten Applikationen wird ausgeführt.
Folgenden Einzelschritte werden abgearbeitet:
Eine Testapplikation wird auf die Steuerung geladen.
Die Testapplikation wird gestartet.
Die Testfälle werden ausgeführt. Wenn in den Testfunktionsbausteinen die Stringvariable
sInfo
oderwsInfo
verwendet wird, erscheint deren Inhalt im Testreport.Der Timeout wird überwacht.
Das Testergebnis wird überprüft und danach Testreport übermittelt.
Applikation wird von der Steuerung entfernt.
Ein Testreport, der alle Testergebnisse enthält, wird generiert.
Tipp
Beachten Sie das Testrepository Default-Test-Repository
. Dort finden Sie das Testskript Examples.IecUnitTest
. In diesem Testskript können Sie einen IEC-Unittest nachvollziehen, also die vorbereitenden Maßnahmen Projekt laden, Gerät aktualisieren und Kommunikationseinstellungen setzen. Dann folgt ein IEC-Unittest. Die Testfälle, die durchlaufen werden, kommen aus dem Projekt Example_IecUnitTest.project
. Sie finden das Projekt im Verzeichnis C:\ProgramData\CODESYS Test Manager
.
Die Beispielskripte sind für eine Steuerung CODESYS Control Win (32 Bit) erstellt. Falls Sie eine andere Steuerung einsetzen, müssen Sie die Parameter der Skript-Aktion UpdateDevice
anpassen.