Variablen
Es gibt ein
kurzes Überblicksvideo zu Variablen,
welches die wichtigsten Punkte dieses Kapitels abdeckt.
Variablen sind von zentraler Bedeutung, wenn es darum geht, die Wiederverwendbarkeit einer Testsuite zu steigern. Zum Einsatz kommen sie vor allem beim Aufruf von Prozeduren. Variablen sind aber auch in vielen anderen Situationen hilfreich.
Variablen können in allen Attributen mit Eingabefeldern verwendet werden. Viele Checkboxen können
über den links davor stehenden
Button in Eingabefelder
umgewandelt werden, dann können dort Wahrheitswerte entweder direkt oder als Variablen
eingetragen werden.
Variablenreferenzen
Es gibt mehrere Möglichkeiten Variablen zu referenzieren:
Referenzierung einfacher Variablen
$(Variablenname)
gibt den Wert einer Variablen zurück.
Ist der Wert keine Zeichenkette, wird aber als Teil einer Zeichenkette ausgewertet oder das Ergebnis als Text genutzt, so wird automatisch die Text-Darstellung des Wertes verwendet.
Referenzierung von Gruppenvariablen
${Gruppe:Name}
greift auf eine Variable
in einer Variablengruppe zu. Damit können zum Beispiel Variablen in
einer Gruppe angesprochen werden, in die Daten aus einer externen Quelle (siehe
Externe Daten)
geladen wurden. Einige Gruppen, zum Beispiel
qftest
, env
und system
, sind immer definiert
und haben besondere Bedeutungen (vgl. Spezielle Gruppen).
Auch hier wird kontextabhängig automatisch die Text-Darstellung des Wertes zurückgegeben.
Referenzierung von Variablen in Skripten und Skriptausdrücken
Für Skripte und Skriptausdrücke (zum Beispiel
$[Jython-Ausdruck]
oder die Bedingung eines
If-Knotens),
ist der Zugriff auf Variablen, die über QF-Test Knoten angelegt wurden,
in Variablen beschrieben.
- Die Runcontext-Methoden
rc.get*
-
Es gibt viele Methoden im Runcontext-Modul, mit denen auf Variablen zugegriffen werden kann, zum Beispiel
rc.getStr
,rc.getInt
,rc.getNum
,rc.getBool
oderrc.getObj
. Eine detaillierte Beschreibung dieser Methoden finden Sie in Die API des Runcontexts. - Das Runcontext-Feld
rc.vars
-
Der Runcontext ermöglicht mit dem
Map
-änlichen Objektrc.vars
einen einfachen Zugriff auf die aktuellen Werte der QF-Test Variablen: Als Alternative fürrc.getObj('Variablenname')
kann im Script direktrc.vars.Variablenname
verwendet werden. Wird über diesen Ausdruck ein Wert zugewiesen, so entspricht dies dem Setzen einer lokalen Variable, analog zurc.setLocal
. - Das Runcontext-Feld
rc.groups
-
Analog zu
rc.vars
ist es möglich, mitrc.groups
auf Gruppenvariablen zuzugreifen: Anstelle vonrc.getObj('Gruppe','Name')
oderrc.getObj('qftest','dir.version')
kannrc.groups.Gruppe.Name
bzw.rc.groups.qftest.dir.version
genutzt werden. Wird diesem Ausdruck ein Wert zugewiesen, so entspricht dies dem Setzen eines Wertes in einer Gruppe, analog zurc.setGroupObject
. Dabei ist zu beachten, dass Elementen in speziellen Gruppen unter Umständen kein Wert zugewiesen werden kann. In diesem Fall wird dann eineReadOnlyPropertyException
geworfen. -
$(Variablenname)
und${Gruppe:Name}
in Jython-Skripten -
In Jython-Skripten und -Skriptausdrücken können QF-Test Variablen mit der gleichen Syntax wie in normalen Knoten referenziert werden. Da das Jython-Skript technisch eine Zeichenkette ist, wird bei der Expansion der Textwert der jeweiligen Variable in den Jython-Code eingefügt.
Diese diese Referenzierungsart wird nicht empfohlen. Wenn der Variablenwert Zeichen wie Rückstriche (
\
) oder Zeilenumbrüche enthält, kann dies zu unerwünschten Effekten führen.
Ermittlung des Wertes einer Variablen
Um zu erklären, wie und warum Variablen an verschiedenen Stellen definiert werden, müssen wir zunächst darauf eingehen, wie der Wert einer Variablen ermittelt wird, wenn diese bei einem Testlauf referenziert wird.
Jede Variablendefinition wird auf einem von zwei Stapeln
abgelegt. Der primäre Stapel ist für direkte
Zuordnungen bestimmt, während der sekundäre Stapel Definitionen von
Rückfallwerten aufnimmt. Wenn der Wert einer Variable zum Beispiel mittels
$(...)
angefordert wird, durchsucht QF-Test zunächst
den primären Stapel von oben nach unten nach einer passenden
Definition. Wird keine solche gefunden, wird die Suche im sekundären
Stapel fortgesetzt, ebenfalls von oben nach unten. Bleibt auch diese
Suche erfolglos, wird eine UnboundVariableException
geworfen, sofern Sie nicht
mittels der speziellen Syntax ${default:varname:defaultvalue}
bzw. im Skript
über rc.withDefault('defaultvalue').getStr('varname')
einen
Defaultwert angegeben haben (vgl. Spezielle Gruppen).
|
|
|||||||
Primärstapel (direkte Zuordnungen) |
Sekundärstapel (Defaultwerte) |
Der Mechanismus unterstützt rekursive bzw. selbstbezogene
Variablendefinitionen. Zum Beispiel bewirkt das Setzen der Variable
classpath
auf den Wert
irgendein/pfad/archiv.jar:$(classpath)
eine Erweiterung des Wertes einer Definition von classpath
mit geringerer Bindungskraft. Existiert keine solche Definition, wird
eine RecursiveVariableException
ausgelöst.
Definition von Variablen
Variablen können an verschiedenen Stellen definiert werden.
- Variablendefinitionstabellen
- Zweispaltige Tabellen werden zum Beispiel im Prozeduraufruf verwendet, um die zu übergebenden Parameternamen und -werte zu definieren oder in einem Prozedur-Knoten, um die Rückfallwerte zu setzen. In jeder Zeile kann eine Variable mit Name und Wert angegeben werden. In vielen weiteren Knoten wie zum Beispiel Testsuite, Testfallsatz und Testfall können Variablen ebenfalls in Tabellen definiert werden.
- Rückgabewert einer Prozedur
- Bei Prozeduraufrufen kann die gerufene Prozedur einen Wert zurückliefern. Dieser wird dann der Variablen mit dem in Variable für Rückgabewert eingetragenen Namen im Prozeduraufruf-Knoten zugewiesen. In der gerufenen Prozedur kann dabei der Typ des zurückgegebenen Objektes mit dem Attribut Expliziter Objekttyp des Return-Knotens festgelegt werden.
- Ergebnis eines Checks
- Eine der möglichen Ergebnisbehandlungen in einem Check-Knoten ist die Zuweisung des Ergebnisses an eine Variable, deren Namen im Attribut Variable für Ergebnis angegeben wurde, zum Beispiel bei einem Check Boolean-Knoten.
- Rückgabewert eines Auslesen-Knotens
- Die Auslesen-Knoten, zum Beispiel Text auslesen, weisen den erhaltenen Wert einer Variablen zu, deren Name im Attribut Variablenname angegeben ist.
- Variable setzen-Knoten
- Über den Variable setzen-Knoten können Variablen ebenfalls definiert werden. Mit dem Attribut Expliziter Objekttyp kann dabei der Typ des zurückgegebenen Objektes festgelegt werden.
- Skript-Knoten
-
In Skripten können über die Methoden
rc.setLocal
,rc.setGlobal
,rc.setLocalJson
etc. Variablen gesetzt werden, die dann in QF-Test Knoten verwendet werden können.setGroupObject
kann genutzt werden, um Variablen in einer Variablengruppe zu setzen. Für weitere Informationen siehe Skripting oder auch Die API des Runcontexts. - Optionendialog
-
Im Optionendialog können Variablen in der Rubrik "Variablen" gesetzt und geändert werden
(vgl. Variablen).
Dies ist besonders für globale, System- und Kommandozeilen-Variablen
interessant.
Abbildung 6.2: Definition von Systemvariablen im Optionendialog
Variablenebenen
Variablen können auf unterschiedlichen Ebenen definiert werden. Wie bereits beschrieben gibt es die grundlegende Unterscheidung bei der Auswertungsreihenfolge der Variablendefinitionen zwischen Primär- und Sekundärstapel. In beiden Stapeln gibt es weitere festgelegte Ebenen.
Primärstapel
Für den Primärstapel gilt folgende Reihenfolge:
Lokale Testfall-Variablen
Lokale Testfall-Variablen liegen im oberen Teil des Primärstapels. Während der Testausführung werden für jeden Knoten, der betreten wird, die definierten Variablen (aber nicht die Rückfallwerte!) oben auf den Stapel gelegt und beim Verlassen desselben wieder entfernt.
Für jeden Knoten, der eine Variablendefinitionstabelle besitzt, wird auf dem Primärstapel eine eigene Ebene angelegt, in der die in der Tabelle definierten Variablen liegen. Variable aus lokalen (nicht globalen!) Variablenzuweisungen werden in einer der vorhandenen Ebenen hinzugefügt beziehungsweise aktualisiert, zum Beispiel der Rückgabewert einer Prozedur, die Ergebnisvariable eines Check- beziehungsweise Auslesen-Knotens oder Variablen, die über Variable setzen oder Skript-Knoten erstellt werden. Die Variable wird der Ebene des obersten Prozedurknotens, oder wenn nicht vorhanden, des Testfallknotens hinzugefügt beziehungsweise aktualisiert - falls die Variable nicht in einer darüber liegenden Ebene (zum Beispiel Sequenz-, Testschritt-, Schleife-, If-Knoten) bereits existiert. In diesem Fall wird der Wert der Variable in dieser höheren Ebene aktualisiert.
Um lokale Variablen anzulegen, muss bei den entsprechenden Knoten das
Attribut Lokale Variable aktiviert sein. Dies kann in den Optionen
voreingestellt werden (siehe Variablen).
Aus Skripten heraus werden lokale Variablen mit den Methoden rc.setLocal
oder rc.setLocalJson
angelegt (siehe Die API des Runcontexts).
Globale Variablen
Wenn in Knoten, die Variablen definieren können, das Attribut Lokale Variable nicht
aktiviert ist, wird die Variable auf der Ebene der globalen Variablen angelegt.
Aus Skripten heraus werden Variablen auf dieser Ebene mit den Methoden rc.setGlobal
oder rc.setGlobalJson
(siehe Die API des Runcontexts),
angelegt.
Hinweis Eine globale Variable kann auch trotz Lokale Variable erzeugt werden, wenn kein Kontext für lokale Variablen verfügbar ist. Dies ist zum Beispiel der Fall, wenn ein Knoten direkt aus den 'Extrasequenzen' ausgeführt wird.
Eine globale Variable bleibt unverändert bestehen, bis sie explizit aktualisiert, gelöscht oder QF-Test beendet wird. Die globalen Variablen "überleben" also einzelne Testläufe. Sie dienen dazu, Werte zwischen voneinander unabhängigen Testfällen oder Prozeduren auszutauschen. Sie sollten aber im Hinterkopf behalten, dass diese Variablen zunächst durch den Ablauf des Tests definiert werden müssen, bevor sie referenziert werden können.
Falls Sie globale Variablen bearbeiten wollen, ist dies entweder im Debug-Modus möglich (siehe Anzeige der Variablen im Debug-Modus – Beispiel) oder im Optionendialog in der Rubrik "Variablen".
Um vor einem
Testlauf die vorhandenen globalen Variablen zu löschen, nutzen Sie den Menüeintrag
»Wiedergabe«-»Globale Variablen löschen«. Läuft QF-Test im Batchmodus (vgl. Aufruf von QF-Test), werden die
globalen Variablen vor der Ausführung jedes mit dem Kommandozeilenargument
-test <Index>|<ID>
angegebenen Tests gelöscht.
Kommandozeilen-Variablen
Beim Start von QF-Test können über Kommandozeilenargumente Variablen definiert werden.
Diese rangieren über den Variablen, die im Testsuite-Knoten spezifiziert sind.
In der Kommandozeile werden die Variablen über das Argument -variable <Name>=<Wert>
gesetzt,
siehe auch Kommandozeilenargumente und Rückgabewerte.
Variablen des Testsuite-Knotens
Auf dieser Ebene des Stapels liegen die Variablen, die im Testsuite-Knoten der aktuellen Testsuite definiert sind. Hier werden typischerweise Variablen angelegt, die für alle Tests der Testsuite gelten und bei Bedarf in einem Batch-Lauf per Kommandozeile überschrieben werden können sollen. Ein typisches Beispiel hierfür ist die Wahl des Browsers, in dem eine Webapplikation ausgeführt werden soll. Diese kann sich dann zwischen interaktiver Testentwicklung und Batch-Ausführung unterscheiden.
Sekundärstapel
Für den Sekundärstapel gilt folgende Reihenfolge:
Rückfallwerte
Beim Betreten eines Knotens, für den Rückfallwerte definiert wurden, werden diese oben auf den Sekundärstapel gelegt. Wenn ein Knoten aus einer anderen Testsuite aufgerufen wird, werden auch die Variablen des Testsuite-Knotens der verlassenen Testsuite vom Primärstapel genommen und oben auf den Sekundärstapel gelegt. Beim Verlassen des Knotens beziehungsweise der Testsuite werden die Variablen wieder vom Sekundärstapel entfernt und im Falle der Testsuite auf den Primärstapel in die entsprechende Ebene verschoben.
Auf dem Sekundärstapel werden nur dann Einträge angelegt, wenn für die entsprechenden Knoten Rückfallwerte definiert wurden oder rufende Testsuiten Variablendefinitionen im Testsuite-Knoten enthalten.
Systemspezifische Variablen
Hier können Pfadnamen, JDK- oder Betriebssystem-spezifische Werte etc. festgelegt werden. Dieser Satz von Definitionen befindet sich immer ganz unten im sekundären Stapel und hat damit die geringste Bindungskraft. Sie können im Optionendialog in der Rubrik "Variablen" gesetzt werden. Die Variablen werden zusammen mit anderen Systemoptionen in der System-Konfigurationsdatei gespeichert.
Anzeige der Variablen im Debug-Modus – Beispiel
Betrachten wir folgendes Beispiel:

Die Sequenz "Login" enthält einen Prozeduraufruf der
Prozedur "login", die zwei Parameter erwartet: user
und password
. Die Standardwerte für Parameter der Prozedur
sind user=username
und password=pwd
. Der
Prozeduraufruf überschreibt diese mit user=myname
und
password=mypassword
.
Die "login" Prozedur enthält selbst Prozeduraufrufe von weiteren Prozeduren. Hier werden keine Parameter übergeben. Die Prozeduren "setUser" und "setPassword" haben in Standardwerte für Parameter jeweils einen Eintrag.
Die folgende Abbildung zeigt die Übersicht der Variablendefinitionen zum Zeitpunkt der Ausführung der Prozedur "setUser".

Lassen Sie uns einen genaueren Blick auf die einzelnen Zeilen der Tabelle werfen:
- Prozedur setUser: Keine Variable definiert.
- Prozeduraufruf setUser: Hier werden keine Variablen übergeben. Dies ist nicht notwendig (wie zum Beispiel bei Java). Bei der Auswertung der Variablendefinitionen sucht QF-Test die Tabelle Zeile für Zeile von oben nach unten durch - unabhängig von Prozedur- oder Testfallgrenzen. Sobald eine Variable mit dem passenden Namen gefunden wird, wird der zugehörige Wert verwendet.
- Prozedur login: Keine Variable definiert.
- Prozeduraufruf login: Hier werden zwei Variablen im Prozeduraufruf definiert. Die Zeile wurde selektiert. Somit sind auf der rechten Seite die definierten Variablen mit ihren Werten zu sehen. Beim aktuellen Ausführungsstand des Tests wird als nächstes die Variable "name" verwendet. Da in dieser Zeile das erste Vorkommen einer Variablen mit diesem Namen ist, wird der zugehörige Wert, "myName", verwendet.
- Sequenz Login: Keine Variable definiert.
- Testfall Test: Keine Variable definiert.
- Globale Variablen: Im Abhängigkeit-Knoten wurde die Variable "client" definiert, da sie in allen Testfällen, die mit der zu testenden Applikation interagieren, benötigt wird. Globale Variablen bleiben unverändert bestehen, bis sie explizit geändert oder gelöscht werden.
- Kommandozeile: Es wurden drei Variablen in der Kommandozeile definiert. Eine davon ist der Name des Browsers, der für den aktuellen Testlauf verwendet werden soll.
- Testsuite: Hier ist der Name des Browsers hinterlegt, der verwendet wird, wenn kein anderer Browser in einer der Zeilen darüber definiert ist.
- Sekundärstapel: Kennzeichnung, dass hier der Primärstapel endet und darunter der Sekundärstapel beginnt.
- Prozedur setUser: Es ist ein Standardwert für die Variable "name" hinterlegt, der verwendet würde, wenn es in keiner der Zeilen darüber eine Variable mit diesem Namen gäbe.
- Prozedur login: Auch hier sind Standardwerte für die Variablen "name" und "password" hinterlegt, die verwendet würden, wenn es in keiner der Zeilen darüber eine Variable mit dem entsprechenden Namen gäbe.
- System: Keine Variable definiert.
Datentypen von Variablen
Die Attributfelder der QF-Test Knoten interpretieren bis auf wenige Ausnahmen die eingegebenen Werte als Text. Bei den Ausnahmen handelt es sich um die Bedingungen von If-, Testfall- und Testfallsatz-Knoten sowie Code-Attribute, die gültige Ausdrücke einer bestimmten Syntax erwarten.
Da die Attribute im Normalfall als Text interpretiert werden, ist eine spezielle Syntax für den Zugriff auf Variablen oder für die Durchführung von Berechnungen oder Textmanipulationen notwendig. Siehe Variablenreferenzen beziehungsweise Skriptausdrücke.
In Skript-Knoten können alle Datentypen genutzt werden, die die jeweilige Skriptsprache zur Verfügung stellt. Innerhalb der Skriptinterpreter können die Datenobjekte von beliebigen Skripten genutzt werden (siehe Variablen). Sie tauchen jedoch nicht auf dem Variablenstapel von QF-Test auf und werden daher weder im Debug-Modus in der Tabelle der Variablendefinitionen angezeigt noch im Protokoll dokumentiert.
Um Variablen aus Skripten auf den Variablenstapel von QF-Test zu legen, stehen die
Runcontext-Methoden rc.setLocal
und rc.setGlobal
zur Verfügung. Hiermit können QF-Test Variablen Textwerte, aber auch Werte mit anderen Datentypen
zugewiesen werden. Um in Variable setzen Knoten Werte zu setzen, die keine Texte
darstellen, können im Attribut Defaultwert Skriptausdrücke genutzt
werden; oder Sie können die Text-Darstellung des Wertes darin eintragen und über
das Attribut Expliziter Objekttyp den gewünschten Objekttyp angeben.
Für den Zugriff auf diese Variablen stehen je nach Bedarf unterschiedliche Methoden zur Verfügung. Für QF-Test Knoten sind sie in Variablenreferenzen beschrieben, für Skripte und Skriptausdrücke in Variablen, speziell für Jython-Skripte in Jython-Variablen.
Eine detaillierte Beschreibung der Methoden finden Sie in Die API des Runcontexts.
JSON-Daten
Bei der Arbeit mit HTTP-Requests werden die Daten oft als
JSON-Objekt bereitgestellt. Wenn Sie das Objekt serialisieren, also in eine
JSON-Zeichenkette umwandeln und einer QF-Test Variablen zuweisen wollen, können
Sie die Methoden rc.setLocalJson()
und rc.setGlobalJson()
des Runcontexts (siehe Die API des Runcontexts) in einem Skript-Knoten verwenden.
Wenn Sie eine JSON-Zeichenkette in ein JSON-Objekt umwandeln wollen, steht
Ihnen in einem Skript-Knoten rc.getJson()
im Runcontext (siehe Die API des Runcontexts)
zur Verfügung.
JSON-Objekte können mit den in Das JSON
Modul beschriebenen
Methoden bearbeitet werden.
Externe Daten
Auf externe Daten kann mit Hilfe von Properties laden, Excel-Datei,
Datenbank, CSV-Datei und Ressourcen laden
Knoten zugegriffen werden. Diese weisen
einem Satz von Definitionen einen Gruppennamen zu. Den Wert einer
Ressource oder Property mit der Bezeichnung Name erhalten Sie
mit der Syntax ${Gruppe:Name}
.
In einem Datentreiber kann ebenfalls über Excel-Datei,
Datenbank und CSV-Datei auf externe Daten zugegriffen
werden. In diesem Fall wird jedoch keine Gruppe erstellt, sondern je Datenzeile
eine Schleifeniteration generiert, in der die Werte des Datensatzes an einfache
Variablen gebunden, deren Name der Titel der entsprechenden Datenspalte ist und
auf die über die Syntax $(Spaltentitel)
zugegriffen werden kann.
Wird ein Test im Batchmodus ausgeführt (vgl. Aufruf von QF-Test), löscht QF-Test
die Ressourcen und Properties vor der Ausführung jedes mit dem Kommandozeilenargument
-test <Index>|<ID>
angegebenen Tests. Im interaktiven Modus werden diese
aufgehoben, um das Erstellen einer Testsuite zu vereinfachen. Vor einem kompletten
Testlauf sollten Sie allerdings mittels »Wiedergabe«-»Ressourcen und Properties löschen« für eine saubere Ausgangsbasis
sorgen.
Spezielle Gruppen
Folgende Variablengruppen sind immer vorhanden. Auf die Werte kann über die Syntax
$(Gruppenname:Variablenname)
zugeriffen werden.
- system
-
Über die Gruppe
system
haben Sie Zugriff auf die SystemProperties
der laufenden Java-VM (für Programmierer:System.getProperties()
). Es handelt sich dabei immer um die VM, mit der QF-Test gestartet wurde, da die Variablen-Expansion dort stattfindet.
So liefert etwa${system:java.class.path}
den Klassenpfad, mit dem QF-Test gestartet wurde oder${system:user.home}
das Heimatverzeichnis des Benutzers. Welche Namen in dersystem
Gruppe definiert sind, hängt vom verwendeten JDK ab. - env
-
Falls das Betriebssystem Umgebungsvariablen wie
PATH
,TMP
oderJAVA_HOME
unterstützt (was auf praktisch allen Systemen der Fall ist, auf denen QF-Test läuft), kann über die Gruppeenv
auf diese Variablen zugegriffen werden. - decrypt
-
9.0+
Über die Gruppe
decrypt
können Sie eine Zeichenkette für die weitere Verarbeitung in QF-Test (zum Beispiel für eine Eingabe in Textfelder, ein Token für einen API-Zugriff oder ein Datenbankpasswort) temporär entschlüsseln. QF-Test ersetzt dabei im Protokoll die Expansion eines entschlüsselten Wertes durch den Platzhalter***
. Zum Verschlüsseln eines Wertes markieren Sie diesen im Variable setzen Knoten und wählen Sie nach einem Rechts-Klick »Text verschlüsseln« aus dem resultierenden Popupmenü.HinweisHinweis: Bei einigen Werten in QF-Test Knoten wird grundsätzlich der endgültige Expansionswert im Protokoll ausgegeben. Begutachten Sie daher im Zweifelsfall die Werte im Protokoll, bevor Sie dieses weitergeben. Beachten Sie darüber hinaus die Hinweise zur Option Salt für Verschlüsselung von Kennwörtern.
- default
-
3.4+
Sie können über die Gruppe
default
einen Defaultwert für eine Variable angeben. Die Syntax hierfür ist${default:varname:defaultvalue}
, in Skriptenrc.withDefault('defaultvalue').getStr('varname')
oder auchrc.getStr('default', 'varname:defaultvalue')
. Dies ist sehr nützlich für Dinge wie generische Komponenten und nahezu überall, wo es einen sinnvollen Defaultwert für eine Variable gibt, da der Defaultwert dann eng mit der Anwendung der Variablen verbunden ist und nicht auf Sequenz oder Testsuite-Ebene definiert werden muss. Natürlich sollten Sie diese Syntax nur verwenden, wenn die Variable nur an einer oder sehr wenigen Stellen benutzt wird. Wenn Sie dieselbe Variable mit dem selben Defaultwert an verschiedenen Stellen verwenden, ist es besser, die normale$(...)
Syntax zu verwenden und den Defaultwert explizit festzulegen, da dieser dann bei Bedarf an einer einzigen Stelle geändert werden kann. - as
-
9.0+
Über die Gruppe
as
lässt sich - ähnlich wie in einem Variable setzen oder Return Schritt - der Typ eines Objektes ändern. Die Syntax hierfür ist${as:type:value}
, wobei invalue
über$(...)
auch Werte in Variablen referenziert werden können. Gültige Werte fürtype
sind:string
,str
,boolean
,number
,object
,pattern
,integer
,int
,long
,float
,double
,cmdline
undjson
. - id
-
3.1+
Die Gruppe
id
dient dazu, QF-Test IDs von Komponenten zu referenzieren. Die Werte in dieser Gruppe expandieren einfach zu sich selbst, d.h."${id:wasauchimmer}"
wird zu"wasauchimmer"
code>. Man kann QF-Test IDs von Komponenten zwar auch ohne diese Gruppe ansprechen, allerdings verbessert die Referenzierung über diese Gruppe die Lesbarkeit der Tests. Vor allem aber werden diese QF-Test IDs auch beim Verschieben der referenzierten Komponente oder Änderungen an ihrer QF-Test ID angepasst. - idlocal
-
4.2.3+
Die Gruppe
idlocal
ist analog zur Gruppeid
, enthält aber zusätzlich den Pfad der aktuellen Testsuite, d.h. aus"${idlocal:x}"
wird"pfad/zur/aktuellen/suite/suite.qft#x"
. Damit lässt sich erzwingen, dass eine Komponente nur aus der Testsuite genommen wird, die zum Zeitpunkt der Expansion aktuell ist, selbst wenn es eine Komponente mit derselben QF-Test ID in der Zieltestsuite für den Prozeduraufruf gibt. - quoteitem
-
4.0+
Mit Hilfe der Gruppe
quoteitem
können Sie bequem Sonderzeichen wie '@', '&' und '%' im textuellen Index eines Unterelements schützen, um zu verhindern, dass dieses als mehrere Unterelemente interpretiert wird. Aus"${quoteitem:user@host.org}"
wird zum Beispiel"user\@host.org"
. - quoteregex, quoteregexp
-
4.0+
Die Gruppe
quoteregex
mit ihrem Aliasquoteregexp
kann zum Schützen von Sonderzeichen mit spezieller Bedeutung in Reguläre Ausdrücke - Regexps verwendet werden. Dies ist hilfreich, wenn reguläre Ausdrücke dynamisch zusammengebaut werden. - quotesmartid
-
6.0.1+
Die Gruppe
quotesmartid
schützt analog zuquoteitem
die Zeichen für Unterelemente '@', '&' und '%', außerdem die Zeichen ':', '=', '<' und '>' mit spezieller Bedeutung für SmartIDs. Aus"${quotesmartid:Name: A & B}"
wird zum Beispiel"Name\: A \& B"
. - qftest
-
Die Gruppe namens
qftest
stellt verschiedene Werte zur Verfügung, die beim Ablauf eines Tests von Bedeutung sein können. Die bisher definierten Werte können Sie den folgenden Tabellen entnehmen.Name Bedeutung 32
oder32bit
Nicht mehr relevant, da die Unterstützung von 32 Bit Java für QF-Test mit Version 8.0 eingestellt wurde.
true wenn QF-Test in einer 32-Bit-Java-VM läuft - was nicht bedeutet, dass dies auf einem 32 Bit Betriebssystem erfolgt - andernfalls false.64
oder64bit
Nicht mehr relevant, da die Unterstützung von 32 Bit Java für QF-Test mit Version 8.0 eingestellt wurde.
true wenn QF-Test in einer 64 Bit Java-VM läuft, andernfalls false.batch
true falls QF-Test im Batch Modus läuft, false im interaktiven Modus. client.baseEngineName.<name>
Der Basisname der primären Engine des Clients, der mit <name> als Client Attribut gestartet wurde, z.B. fx
.client.browser.<name>
Der Name bzw. Typ des Browsers des Clients, der mit <name> als Client Attribut gestartet wurde, z.B. safari
. Steht nur für Web-Clients zur Verfügung.client.deviceName.<name>
Ein Name für das (emulierte) Gerät des Clients, der mit <name> als Client Attribut gestartet wurde, z.B. Pixel_3
. Steht nur zur Verfügung für Android-Clients nach der Instrumentierung und entspricht dort bei emulierten Geräten dem AVD-Namen.client.deviceType.<name>
Der Typ des (emulierten) Geräts des Clients, der mit <name> als Client Attribut gestartet wurde. Kann die Werte emulator
(für ein emuliertes Gerät) unddevice
(für ein real angeschlossenes Gerät) annehmen. Steht nur zur Verfügung für Android-Clients nach der Instrumentierung.client.connectionMode.<name>
Der Name des Verbindungsmodus des Clients, der mit <name> als Client Attribut gestartet wurde. Gültige Werte sind qfdriver
,cdpdriver
,webdriver
undembedded
. Steht nur für Web-Clients zur Verfügung.client.engine.<name>
Die primäre Engine des Clients, der mit <name> als Client Attribut gestartet wurde. Das Ergebnis besteht dabei aus dem Basisnamen der Engine und einem numerischen Index, z.B. fx0
.client.engineNames.<name>
Eine Liste aller verbundenen Engines des Clients, der mit <name> als Client Attribut gestartet wurde, z.B. [fx0, web_fx0]
.client.exitCode.<name>
Der Rückgabewert des letzten Prozesses, der mit <name> als Client Attribut gestartet wurde. Ist der Prozess noch aktiv, ist das Ergebnis leer. client.mainVersion.<name>
Der Hauptversion des Browsers bzw. des Geräte-Betriebssystems des Clients, der mit <name> als Client Attribut gestartet wurde, z.B. 121
. Steht nur zur Verfügung für Web-Clients, nachdem das erste Browserfenster geöffnet wurde, und für Android-Clients nach der Instrumentierung.client.output.<name>
Die Ausgaben des letzten Prozesses, der mit <name> als Client Attribut gestartet wurde. Das Maximum an gespeichertem Text wird durch die Option Maximalgröße des Terminals für einen Client (kB) bestimmt. client.SDKVersion.<name>
Der SDK-Version des Geräte-Betriebssystems des Clients, der mit <name> als Client Attribut gestartet wurde, z.B. 29
. Steht nur zur Verfügung für Android-Clients nach der Instrumentierung.client.stdOut.<name>
Die vom letzten Prozesses, der mit <name> als Client Attribut gestartet wurde, auf den Standardausgabestream (stdout) geschriebenen Ausgaben. Das Maximum an gespeichertem Text wird durch die Option Maximalgröße des Terminals für einen Client (kB) bestimmt. client.stdErr.<name>
Die vom letzten Prozesses, der mit <name> als Client Attribut gestartet wurde, auf den Fehlerausgabestream (stderr) geschriebenen Ausgaben. Das Maximum an gespeichertem Text wird durch die Option Maximalgröße des Terminals für einen Client (kB) bestimmt. client.version.<name>
Der Browserversion bzw. die Version des Geräte-Betriebssystems des Clients, der mit <name> als Client Attribut gestartet wurde, z.B. 121.10.2967.10
. Steht nur zur Verfügung für Web-Clients, nachdem das erste Browserfenster geöffnet wurde, und für Android-Clients nach der Instrumentierung.clients
Eine Liste der Namen der aktiven Client-Prozesse, mit Zeilentrennern getrennt. clients.all
Eine Liste der Namen aller Client-Prozesse, mit Zeilentrennern getrennt. Die Liste enthält aktive Prozesse ebenso wie kürzlich beendete, analog zum "Clients" Menü. count.exceptions
Anzahl der Exceptions im aktuellen Testlauf. count.errors
Anzahl der Fehler im aktuellen Testlauf. count.warnings
Anzahl der Warnungen im aktuellen Testlauf. count.testCases
Gesamtanzahl der Testfälle (ausgeführt und übersprungen) im aktuellen Testlauf. count.testCases.exception
Anzahl der Testfälle mit Exceptions im aktuellen Testlauf. count.testCases.error
Anzahl der Testfälle mit Fehlern im aktuellen Testlauf. count.testCases.expectedToFail
Anzahl der erwartet fehlgeschlagenen Testfälle im aktuellen Testlauf. count.testCases.ok
Anzahl der erfolgreichen Testfälle im aktuellen Testlauf. count.testCases.ok.percentage
Prozentsatz der erfolgreichen Testfälle im aktuellen Testlauf. count.testCases.skipped
Anzahl der übersprungenen Testfälle im aktuellen Testlauf. count.testcases.notImplemented
Anzahl der nicht implementierten Testfälle im aktuellen Testlauf. count.testCases.run
Anzahl der ausgeführten Testfälle im aktuellen Testlauf. count.testSets.skipped
Anzahl der übersprungenen Testfallsätze im aktuellen Testlauf. dir.cache
Das Cache-Verzeichnis von QF-Test dir.groovy
Verzeichnis von Groovy dir.javascript
Verzeichnis von JavaScript dir.jython
Verzeichnis von Jython dir.log
Das Logverzeichnis von QF-Test dir.plugin
Das Pluginverzeichnis von QF-Test dir.root
Wurzelverzeichnis von QF-Test dir.runlog
Protokollverzeichnis von QF-Test dir.system
Das systemspezifische Konfigurationsverzeichnis von QF-Test. dir.user
Das anwenderspezifische Konfigurationsverzeichnis von QF-Test dir.version
Versionsspezifisches Verzeichnis von QF-Test engine.<componentId>
Ermittelt die GUI-Engine, die für die angegebene Komponente zuständig ist (vgl. GUI-Engines). language
Die Sprache in welcher QF-Test seine graphische Oberfläche darstellt. license
Der Pfad der Lizenzdatei systemCfg
Der Pfad der Systemkonfigurationsdatei userCfg
Der Pfad der benutzerspezifischen Konfigurationsdatei executable
Die ausführbare qftest
Programmdatei passend zur aktuell laufenden QF-Test Version, inklusive vollem Pfad zu derenbin
Verzeichnis und mit.exe
Anhang unter Windows. Dies ist hilfreich, falls Sie QF-Test aus QF-Test starten wollen, z.B. um einen Daemon-Aufruf auszuführen oder Reports zu generieren.isInRerun
"true", wenn aktuelle Ausführung nochmals ausgeführt wird, sonst "false", Details siehe Fehlerhafte Knoten sofort wiederholen. isInRerunFromLog
"true", wenn Testlauf aus dem Protokoll nochmals gestartet wurde, sonst "false", Details siehe Erneute Ausführung aus dem Protokoll. java
Standard Java-Programm ( javaw
unter Windows,java
unter Linux) oder das explizit mittels-java <Programm>
(abgekündigt) angegebene Java-Programm.java.mainVersion
Die Hauptversion des JRE mit dem QF-Test aktuell läuft, wobei 8 für Java 1.8 genommen wird, also z.B. 8, 11 oder 17. java.subVersion
Die Unterversion des JRE mit dem QF-Test aktuell läuft. Für Java 8 wird die Unterversion nach dem '_ genommen, was z.B. für java.version 1.8.0_302 zu 302 führt. Für Java 9 oder höher ist dies die normale Unterversion, also z.B. 9 in Fall von java.version 11.0.9. linux
"true" unter Linux, andernfalls "false" macOS
"true" unter macOS, andernfalls "false" os.fullVersion
Die vollständige Version des Betriebssystems os.mainVersion
Die Hauptversion des Betriebssystems, z.B. "10" für Windows 10 os.name
Der Name des Betriebssystems os.version
Die konkrete Version des Betriebssystems. Unter Windows kann diese ggf. nicht vollständig sein. In diesem Fall sollten Sie auf os.fullversion
zurückgreifen.project.dir
Das Verzeichnis des aktuellen Projektes. Die Variable ist nicht definiert, wenn die aktuelle Test suite sich nicht in einem Projekt befindet. rerunCounter
Nummer des aktuellen Versuchs der Neuausführung, sonst immer 0 (siehe Fehlerhafte Knoten sofort wiederholen). return
Der letzte mittels eines Return Knotens aus einer Prozedur zurückgegebene Wert. runID
Die Run-ID des aktuellen Testlaufs. Nähere Informationen zur Run-ID finden Sie in Abschnitt 24.1. screen.height
Bildschirmhöhe in Pixel screen.width
Bildschirmbreite in Pixel skipNode
Dieser spezielle Wert ist nur für erfahrene Anwender. Er weist QF-Test an, die Ausführung des aktuellen Knotens zu überspringen. Sein primärer Nutzen ist als Wert für eine Variable im Attribut Text eines Texteingabe Knotens, dessen Attribute Zielkomponente zunächst leeren gesetzt ist. Ein leerer Wert würde hier zu einem Löschen des Textfeldes führen, $_{qftest:skipnode} hingegen das Feld unverändert lassen. Weiterhin kann skipnode für besondere Fälle der Ablaufsteuerung eingesetzt werden, indem z.B. eine Variable im Kommentar eines Knotens definiert und ihr selektiv der Wert $_{qftest:skipnode} übergeben wird. Beachten Sie bitte, dass hierfür praktisch immer die Lazy Binding Syntax '$_' verwendet werden sollte, da ansonsten die Expansion im Parameter eines Prozeduraufruf Knotens zum Überspringen des gesamten Aufrufs führen würde. suite.dir
Verzeichnis der aktuellen Suite suite.file
Dateiname der aktuellen Suite ohne Verzeichnis suite.path
Dateiname der aktuellen Suite mit Verzeichnis suite.name
Der Name der aktuellen Testsuite. testCase.name
Der Name des aktuellen Testfalls, leer falls im Moment kein Testfall ausgeführt wird. testCase.id
Die QF-Test ID des aktuellen Testfalls, leer falls im Moment kein Testfall ausgeführt wird. testCase.qName
Der qualifizierte Name des aktuellen Testfalls, inklusive der Namen seiner Testfallsatz Parentknoten. Leer falls im Moment kein Testfall ausgeführt wird. testCase.reportName
Der expandierte Report-Name des aktuellen Testfalls, leer falls im Moment kein Testfall ausgeführt wird. testCase.splitLogName
Der qualifizierte Name des aktuellen Testfalls als Dateiname, inklusive der Namen seiner Testfallsatz Parentknoten als Verzeichnisse. Leer falls im Moment kein Testfall ausgeführt wird. testSet.name
Der Name des aktuellen Testfallsatzes, leer falls im Moment kein Testfallsatz ausgeführt wird. testSet.id
Die QF-Test ID des aktuellen Testfallsatzes, leer falls im Moment kein Testfallsatz ausgeführt wird. testSet.qName
Der qualifizierte Name des aktuellen Testfallsatzes, inklusive der Namen seiner Testfallsatz Parentknoten. Leer falls im Moment kein Testfallsatz ausgeführt wird. testSet.reportName
Der expandierte Report-Name des aktuellen Testfallsatzes, leer falls im Moment kein Testfallsatz ausgeführt wird. testSet.splitLogName
Der qualifizierte Name des aktuellen Testfallsatzes als Dateiname, inklusive der Namen seiner Testfallsatz Parentknoten als Verzeichnisse. Leer falls im Moment kein Testfallsatz ausgeführt wird. testStep.name
Der Name des aktuellen Testschritts (inkl. @teststep doctag), leer falls im Moment kein Testschritt ausgeführt wird. testStep.qName
Der qualifizierte Reportname des aktuellen Testschritts (inkl. @teststep doctag), inklusive der Reportnamen seiner Testschritt Parentknoten aber ohne Testfall und Testfallsatz Parentknoten. Leer falls im Moment kein Testschritt ausgeführt wird. testStep.reportName
Der expandierte Report-Name des aktuellen Testschritts (inkl. @teststep doctag), leer falls im Moment kein Testschritt ausgeführt wird. thread
Der Index des aktuellen Threads. Immer 0, es sei denn QF-Test wird mit dem Kommandozeilenargument -threads <Anzahl>
gestartet.threads
Die Anzahl der parallelen Threads. Immer 1, es sei denn QF-Test wird mit dem Kommandozeilenargument -threads <Anzahl>
gestartet.version
QF-Test Version version.build
QF-Test Buildnummer windows
"true" unter Windows, andernfalls "false" Tabelle 6.1: Definitionen in der Gruppe qftest
3.0+6.9
Immediate und Lazy Binding
Es gibt einen sehr subtilen Aspekt bei der Verwendung von QF-Test Variablen auf den wir noch genauer eingehen müssen:
Wenn ein Satz von Variablendefinitionen auf einen der beiden Stapel gelegt wird gibt es zwei Möglichkeiten zur Behandlung von Referenzen auf Variablen im Wert einer Definition. Hat z.B. die Variable namens 'x' den Wert '$(y)', kann dieser Wert wortwörtlich gespeichert werden, so dass der Wert von '$(y)' erst zu einem späteren Zeitpunkt ermittelt wird, wenn irgendwo '$(x)' referenziert wird. Alternativ kann der Wert von '$(y)' schon beim Binden der Variablen 'x' ermittelt und als Wert von x abgelegt werden. Der erste Ansatz wird als "Lazy Binding" oder "Late Binding" bezeichnet, der zweite als "Immediate Binding".
Der Unterschied zwischen beiden ist natürlich der Zeitpunkt der Expansion und damit der Kontext in dem eine Variable expandiert wird. In den allermeisten Fällen ist das Ergebnis das gleiche, aber es gibt Situationen in denen es von großer Bedeutung ist, Lazy oder Immediate Binding zu verwenden. Betrachten wir die folgenden zwei Beispiele:
Eine Testsuite-Bibliothek stellt eine Prozedur zum Start des SUT mit verschiedenen JDK Versionen bereit. Die Variable 'jdk' wird als Parameter an diese Prozedur übergeben. Zur einfacheren Nutzung definiert der Autor der Bibliothek weitere hilfreiche Variablen auf Testsuite-Ebene, z.B. 'javabin' für das ausführbare Java-Programm mit dem Wert '/opt/java/$(jdk)/bin/java'. Zu dem Zeitpunkt, zu dem 'javabin' in den Testsuite Variablen gebunden wird, könnte 'jdk' noch undefiniert sein, so dass Immediate Binding zu einem Fehler führen würde. Doch selbst wenn 'jdk' mit einem Standardwert belegt ist hat Immediate Binding nicht den gewünschten Effekt, da sich der Wert von 'javabin' durch Übergabe eines anderen Wertes für 'jdk' an die Prozedur nicht mehr ändert. Lazy Binding ist hier also die Methode der Wahl.
Betrachten wir eine andere Bibliothek mit einer Prozedur zum Kopieren einer Datei. Die zwei Parameter namens 'source' und 'dest' legen die Ausgangsdatei und das Zielverzeichnis fest. Der Aufrufer der Prozedur möchte die Datei 'data.csv' aus dem Verzeichnis seiner Testsuite an einen anderen Ort kopieren. Die nahe liegende Idee ist, für den Parameter 'source' den Wert '${qftest:suite.dir}/data.csv' an die Prozedur zu übergeben. Mit Immediate Binding liefert '${qftest:suite.dir}' in der Tat das Verzeichnis der aufrufenden Suite. Wird allerdings Lazy Binding verwendet, findet die Expansion erst innerhalb der Prozedur statt, so dass '${qftest:suite.dir}' das Verzeichnis der Bibliotheks-Suite liefert, was im Allgemeinen nicht den gewünschten Effekt hat.
In QF-Test Versionen bis einschließlich 2.2 wurde ausschließlich Lazy Binding unterstützt. Wie die obigen Beispiele zeigen, sind aber beide Varianten sinnvoll und notwendig. Immediate Binding ist aber intuitiver und leichter nachzuvollziehen und daher inzwischen die Standard-Methode (dies kann aber mittels der Option Werte von Variablen beim Binden sofort expandieren geändert werden). Die Option Lazy Binding verwenden falls sofortiges Expandieren scheitert ergänzt diese und ermöglicht eine einfache Migration von älteren Testsuiten zum Gebrauch von Immediate Binding. Die Warnungen, die in diesem Zusammenhang ausgegeben werden, helfen Ihnen, die wenigen Stellen zu lokalisieren, an denen Sie wie unten beschrieben explizit Lazy Binding verwenden sollten. Bis auf die äußerst seltenen Fälle, in denen Lazy Binding benötigt wird, Immediate Binding aber auch funktioniert, so dass kein Rückgriff auf Lazy Binding gemacht wird, sollten alle Tests ohne Änderungen lauffähig sein.
In den wenigen Fällen, in denen es einen Unterschied macht, ob eine Variable mittels Immediate oder Lazy Binding definiert wird, kann dies unabhängig von der Voreinstellung durch eine alternative Variablen-Syntax erzwungen werden. Für Immediate Binding verwenden Sie '$!' anstatt nur '$', Lazy Binding erhalten Sie mittels '$_'. Um z.B. auf Testsuite-Ebene eine Variable zu definieren, deren Wert eine Datei im Verzeichnis dieser Suite ist, verwenden Sie '$!{qftest:suite.dir}/somefile'. Wenn Sie wie in obigem 'jdk' Beispiel Lazy Binding benötigen, verwenden Sie '$_(jdk)'.
Hinweis Mit Lazy Binding war es egal, in welcher Reihenfolge Variablen oder Parameter in einem Knoten oder Datentreiber definiert waren, da während des Bindens keine Expansion stattfand. Bei Immediate Binding werden Variablen von oben nach unten, bzw. bei Datentreibern von links nach rechts expandiert. Das bedeutet, dass die Definition von x=1 und y=$(x) funktioniert und y den Wert 1 erhält, wenn x zuerst definiert wird. Kommt hingegen die Definition von y zuerst, führt dies zu einem Fehler oder dem oben beschriebenen Rückfall auf Lazy Binding.