Benutzerdefinierte Utilities¶
Derzeit existieren zwei Arten von Utilities: AXSUtility und UserUtility.
Dabei handelt es sich um Python-Module, deren Aufbau in den folgenden Abschnitten näher
erläutert wird. Um die Utilties verwenden zu können, müssen diese im Utilities-Verzeichnis
(wie im Menü angegeben) oder einem
Unterverzeichnis davon gespeichert werden. Beispiele zu den jeweiligen Utilityarten finden Sie im
ecu.test Installationsverzeichnis unter Templates/DefaultData/Utilities/ExampleUtilities.
Über den Utility Wizard können Sie sich ein Grundgerüst für ein Utility generieren lassen.
AXSUtility¶
Es besteht die Möglichkeit, ein AXSUtility als Testschritt einzufügen. Dabei wird das Utility auf sich selbst gemappt, d.h. das AXSUtility stellt das Interface und die Implementierung bereit.
Der Vorteil ist, dass der Benutzer bei einem solchen Utility nur noch das Interface schreiben und die Run()-Methode implementieren muss. Das Interface beschreibt die Eingangsparameter und die Rückgabewerte. Innerhalb der Run()-Methode kann dann auf die Parameter lesend und schreibend zugegriffen werden. Alles weitere (Dialog, Serialisierung, Reporting, …) wird automatisch von ecu.test erstellt.
Mitgeliefertes Beispiel
Im Tab Utilities existiert unter Beispiele das AXSUtility „SimpleCalculationExample“ zur Demonstration. Sollte dies hier noch nicht vorhanden sein, können Sie wie im Abschnitt Workspace Erstellung beschrieben die Beispiele in den gewählten Workspace kopieren.
Man kann bei der Operation zwischen Addition, Subtraktion, Multiplikation und Division wählen. Die gewählte Operation wird bei der Ausführung auf die beiden Operanden a und b angewandt.
Bei einem Rechtsklick auf „SimpleCalculationExample“ kann ausgewählt werden, um die Implementierung zu betrachten. Alternativ ist dieser Editor auch über den Utility Wizard erreichbar.
Erstellung eines AXSUtility¶
Der zweite Eintrag im Utility Wizard:
Interfacedefinition
In der Methode GetInterface(cls) muss nun das Interface des AXSUtility definiert werden.
Die Argumente und Rückgabewerte werden als Constraints beschrieben.
Derzeit ist es nur möglich mit skalaren Größen (also einfachen Datentypen wie Zahlen oder Texten) zu arbeiten.
NumericType
Eine Zahl. Wahlweise mit einer physikalischen Einheit. Der Konstruktor erwartet vier Parameter:
def __init__(self, name, min, max, step)Der erste Parameter definiert den Namen. Zusätzlich können eine optionale Unter- und Obergrenze und eine Schrittweite angegeben werden, welche eingehalten werden müssen. Wird
Noneübergeben, dann entfällt die Beschränkung. Über die Methodedef SetUnitFromStr(self, unitName)kann anschließend die Einheit gesetzt werden, wobei hier die Einheit als Text (wie in ecu.test angezeigt) angegeben werden muss.
Über die Methode
def SetDefaultValue(self, defaultValue)kann der initiale Wert beim Einfügen des Utilities festgelegt werden. Wird dieser Wert nicht explizit angegeben, so werden der Minimalwert oder 0 verwendet.
TextType
Ein Textwert. Der Konstruktor erwartet ausschließlich den Namen als Parameter:
def __init__(self, name)Es besteht die Möglichkeit über
def AddTextEntry(self, entry)einen Wertebereich für die Auswahl eines Wertes anzugeben. Die mögliche Auswahl wird im Dialog durch eine Combobox angezeigt.
Über die Methode
def SetDefaultValue(self, defaultValue)kann der initiale Wert beim Einfügen des Utilities festgelegt werden. Wird dieser Wert nicht explizit angegeben, so werden der erste Textwert oder eine leere Zeichenkette verwendet.
Dem Interface werden über
def AddArgument(self, argument)
die Argumentenconstraints bzw. über
def AddReturn(self, returnValue)
die Rückgabeconstraints übergeben.
Die Implementierung
Innerhalb der Methode
def OnRun(self, userExcInst, testEngine)
kann der Benutzer mittels des Objekts userExcInst lesend auf die Eingabeparameter und schreibend auf
die Rückgabewerte zugreifen. userExcInst ist eine Instanz der Klasse UserExecInst, welche folgende
Methoden zur Behandlung eines Values-Objekts (nur dieser wird derzeit unterstützt) bereitstellt:
def GetArgumentValue(self, name)def GetRawArgumentValue(self, name)Abfragen der Argumente anhand deren Namen. Die erste Methode liefert den Wert gekapselt in einem Value-Objekt zurück, die zweite den konkreten Wert als Zahl oder Text.
def SetReturnValue(self, name, value)def SetRawReturnValue(self, name, rawvalue)Setzen der Rückgabewerte mit den Namen value/rawvalue. Die erste Methode erwartet einen Parameter der in einem Value-Objekt gekapselt ist, die zweite Methode den konkrete Wert als Zahl oder Text. Ein nicht übergebenes/gemapptes Argument entspricht
None.
Optional können noch die Methoden
def OnPreProcess(self, testEngine)
oder
def OnPreProcessEx(self, userExcInst, testEngine)
sowie
def OnPostProcess(self, testEngine)
und
def GetReportInfos(self)
überschrieben werden. In OnPreProcessEx ist dabei der Zugriff auf die Eingabeparameter auf die selbe
Weise wie in OnRun möglich. Es können jedoch nur Parameter abgefragt werden, für die ein konstanter
Wert (d.h. ohne Zugriff auf Testfallvariablen) übergeben wird. Die Methode OnPreProcessEx wird dabei
für jedes nicht ausgeblendete Vorkommen des Utility-Aufrufs im Testfall einmal mit der entsprechenden
Parametrierung aufgerufen, ohne Rücksicht auf Loops, If-Then-Else etc.
Info
Insbesondere wenn man ein AXSUtility mehrfach im Testfall benutzt, muss man das durch GetReportInfos
zurückgegebene Dict in einer Liste (oder Deque) halten. Hintergrund ist, dass z.B. bei
zweifacher Verwendung eines AXSUtility zunächst zweimal die Methode OnRun aufgerufen wird, bevor
ein Aufruf von GetReportInfos erfolgt. Hält man die ReportInfos hingegen nur direkt in einem Dict,
so wird dieses beim zweiten Aufruf von OnRun überschrieben. Der anschließende zweimalige
Aufruf von GetReportInfos liefert dann immer das Dict der zweiten Ausführung des Utility.
In den Beispielen (siehe Abschnitt Workspace Erstellung) demonstriert das
Utility „LinspaceExample“ die korrekte Verwendung von GetReportInfos.
Nach dem Schließen des Utility Wizards kann das AXSUtility als Testschritt eingefügt und ausgeführt werden:
Im Report erkennt man ein Utility, welches auf sich selbst gemappt ist (also das Interface und die Implementierung bereitstellt) an der Aktion „UTILITY -> UTL“:
UserUtility¶
Der konkrete Aufbau eines Userutilities ist in der Dokumentation zur UserUtility API erläutert. Werden Userutilities aktualisiert und über den Menüeintrag „Benutzerbibliotheken aktualisieren“ (Shortcut Ctrl+Shift+R) neu geladen, dann müssen geöffnete Packages die diese Utilities verwenden geschlossen und neu geöffnet werden, damit die Aktualisierung wirksam wird.