Skripting (Jython, Groovy und JavaScript)
Dieser Abschnitt erläutert die technischen Details der Integration von Jython, Groovy und JavaScript in QF-Test. Er enthält eine vollständige Referenz der API, die Jython-, Groovy- und JavaScript-Skripten zur Interaktion mit QF-Test zur Verfügung steht. Eine weniger technische Einführung finden Sie in Kapitel 11.
Pfad für das Laden der Module
Der Loadpath für Module werden in den Skriptsprachen aus verschiedenen Teilen in folgender Reihenfolge zusammengesetzt:
- Das benutzerdefinierte Skript-Verzeichnis.
-
Das Verzeichnis
qftest/qftest-9.0.0/<Name der Skriptsprache>
Zusätzlich wird dem Pfad während der Ausführung eines Server-Skript oder SUT-Skript Knotens das Verzeichnis der Testsuite vorangestellt.
Das Verzeichnis
qftest/qftest-9.0.0/<Skriptsprache>
enthält
interne Module der jeweiligen Skriptsprache. Sie sollten diese Dateien nicht
modifizieren, da sie sich jederzeit ändern können und auf die
jeweilige Version von QF-Test zugeschnitten sind.
Ihre eigenen Module sollten Sie in das benutzerdefinierte Skript-Verzeichnis legen.
Die Pfade zu diesen Verzeichnissen finden Sie via
»Hilfe«-»Info«
unter "Systeminfo" als dir.<Skriptsprache>.
Dabei müssen die Module die jeweilige Endung haben
(.py
für Jython, .groovy
für Groovy und .js
für JavaScript) haben.
In Jython können Sie die System Property
python.path
nutzen, um weitere Verzeichnisse zum Loadpath hinzuzufügen.
Das Plugin Verzeichnis
Mit den Skriptsprachen kann auch auf Java-Klassen und Methoden zugegriffen werden, die nichts speziell mit QF-Test zu tun haben, indem diese Klassen einfach importiert werden, z.B.:
from java.util import Date from java.text import SimpleDateFormat print SimpleDateFormat("yyyy-MM-dd").format(Date())
Zugriff gibt es auf alle Klassen im Java-Klassenpfad, das heißt die der Standard Java-API
sowie QF-Test's eigene Klassen. Beachten Sie, dass die Umgebungsvariable CLASSPATH
von QF-Test ignoriert wird; falls nötig, kann aber QFTEST_CLASSPATH
mit demselben Wert
definiert werden. Für das SUT hängt vieles vom verwendeten ClassLoader Konzept ab.
Insbesondere bei WebStart und Eclipse/RCP ist es schwierig, Klassen des SUT direkt zu
importieren.
Zusätzlich gibt es Plugin Verzeichnisse, in die Sie einfach eine jar
Datei stellen können, um sie in Skripten verfügbar zu machen. QF-Test sucht dazu nach einem
plugin
Verzeichnis.
Das aktuell verwendete Plugin-Verzeichnis finden Sie via »Hilfe«-»Info« unter "Systeminfo" als dir.plugin.
Das Plugin-Verzeichnis kann auch über das Kommandozeilenargument -plugindir <Verzeichnis>
geändert werden.
Jar-Dateien im primären Pluginverzeichnis stehen sowohl
Server-Skript, als auch SUT-Skript Knoten zur
Verfügung. Um eine jar Datei ausschließlich für
Server-Skripte oder ausschließlich für
SUT-Skripte bereitzustellen, stellen Sie diese
stattdessen in das zugehörige Unterverzeichnis namens
qftest
bzw. sut
.
Initialisierung (Jython)
Beim Start von QF-Test und des SUT wird ein Jython-Interpreter
erzeugt und in die Applikation eingebettet. Für QF-Test wird dabei das
Modul qftest
geladen, für das SUT das Modul
qfclient
. Beide basieren auf dem Modul
qfcommon
, das den gemeinsamen Code enthält. Diese
Module werden benötigt, um die Schnittstelle zum Runcontext und den
globalen Namespace bereitzustellen.
Anschließend wird der Loadpath sys.path
nach Ihren
persönlichen Modulen für die Initialisierung durchsucht. Für QF-Test
wird die Datei qfserver.py
geladen, für das SUT die
Datei qfsut.py
. In beiden fällen werden die Dateien
mittels execfile
ausgeführt, womit der Inhalt der
Dateien direkt im globalen Namespace landet. Dies ist für
Initialisierungsdateien von Vorteil, da alle Module, die von diesen
importiert werden, direkt für Server-Skript und
SUT-Skript Knoten zur Verfügung stehen. Bedenken Sie bei
Ihren Initialisierungsdateien, dass zu diesem Zeitpunkt noch kein
Runcontext und kein Testsuite-spezifisches Verzeichnis in
sys.path
zur Verfügung stehen.
Die Namespace Umgebung für Skript-Knoten (Jython)
Die Umgebung in der Server-Skripte oder SUT-Skripte ausgeführt werden, wird durch den globalen und lokalen Namespace bestimmt, die während der Ausführung definiert sind. Namespaces sind Jython Dictionaries, welche die Bindungen für die globalen und lokalen Variablen beinhalten.
Der globale Namespace wird von allen Skripten, die in demselben
Jython-Interpreter laufen, gemeinsam genutzt. Er enthält zunächst
nur die Klassen TestException
und
UserException
, das Modul qftest
bzw.
qfclient
für QF-Test bzw. das SUT, und alles, was in
qfserver.py
bzw. qfsut.py
definiert und
importiert wurde. Wenn Sie in einem Skript eine Variable mit Hilfe
des global
Statements als global deklarieren und ihr
einen Wert zuweisen, wird diese in den globalen Namespace
aufgenommen und steht damit für weitere Skripte zur
Verfügung. Zusätzlich nimmt QF-Test automatisch alle Module in den
globalen Namespace auf, die während der Ausführung eines Skripts
importiert werden.
Der lokale Namespace wird für jedes Skript neu erstellt. Beim Aufruf
des Skripts enthält er das Objekt rc
, die Schnittstelle
zu QF-Tests Runcontext, sowie true
und false
mit den Werten 1
und 0
zur besseren
Integration mit QF-Test.
Für den Zugriff auf und das Setzen von Variablen in einem fremden
Jython-Interpreter, stehen die Runcontext Methoden
fromServer
, fromSUT
, toServer
und toSUT
zur Verfügung.
Die API des Runcontexts
Das Runcontext-Objekt rc
ist die Schnittstelle
zum Ausführungszustand des laufenden Tests in QF-Test. Die Verwendung
einer zusätzlichen Schicht erlaubt Änderungen an der Implementierung von
QF-Test, ohne die Schnittstelle für Skripte zu gefährden.
Es folgt eine alphabetische Aufstellung aller Methoden des
Runcontext-Objekts rc
. Die verwendete Syntax ist ein
Gemisch aus Java und Python. Python unterstützt zwar selbst
keine statische Typisierung, die Parameter werden jedoch an Java
weitergereicht, so dass falsche Typen Exceptions auslösen können.
Folgt einem Parameter ein '='-Zeichen und ein Wert, ist dies der
Defaultwert des Parameters und eine Angabe beim Aufruf ist
optional.
Hinweis
Die Groovy-Syntax für Keyword-Parameter unterscheidet sich von Jython. Groovy verwendet
':' statt '='. Dies ist besonders tückisch, weil z.B. rc.logMessage("bla",
report=true)
durchaus legaler Groovy-Code ist, der allerdings nicht den
gewünschten Effekt hat. Das '=' ist hierbei eine Zuweisung mit dem Wert true, der dann
ganz einfach als zweiter Parameter übergeben wird, so dass der Aufruf äquivalent ist zu
rc.logMessage("bla", true)
. Hierbei wird true aber für
dontcompactify
statt report
verwendet. Die korrekte Version
für Groovy lautet rc.logMessage("bla", report:true)
.
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Der Parameter expand
Die Methoden
getStr
, getObj
, getInt
, getNum
, getBool
,
getPattern
und getJson
unterstützen einen optionalen boolschen Parameter expand
.
Dieser legt fest, ob die Variable bei der Auswertung rekursiv expandiert werden soll,
das heißt, ob eine in der String-Darstellung des Variablenwerts enthaltene Zeichenkette, die (zufällig) die QF-Test
Variablensyntax $(irgendwelche_Zeichen) hat, als Variable expandiert oder
als einfacher Text behandelt werden soll. Ist dieser nicht angegeben oder null
, so
führt QF-Test die Expansion (auch rekursiv) genau dann durch, wenn der Variablenwert ein String ist.
Um Probleme zu vermeiden werden bestimmte Zeichenketten, zum Beispiel das Ergebnis eines Text auslesen
Knotens, die Client-Ausgabe aus der speziellen Gruppe ${qftest:client.output.<name>}
oder der Rückgabewert
der Standard-Prozedur qfs.utils.readTextFromFile
nicht automatisch expandiert, sondern nur,
wenn der expand
Parameter explizit auf true
gesetzt wurde.
Wenn Sie diesen Parameter angeben
wollen, ohne eine Gruppe zu spezifizieren, müssen Sie die Python Keyword Syntax verwenden, um
Konflikte mit zum Beispiel der Methode getStr(String group, String
name)
zu vermeiden, also rc.getStr("var",
expand=0)
an Stelle von rc.getStr("var", 0)
- andernfalls
würde in der Gruppe var
nach der Property 0
gesucht.
- Beispiel
-
Wenn die QF-Test Variablen die folgenden Werte besitzen,
Variablenreferenz Wert $(simplevar) foo $(nestedvar) Ein Wert: $(simplevar) ${group:var} Ein Wert: $(simplevar) Tabelle 50.1: QF-Test Variable für nachfolgendes Bespielskript hat der Parameter
expand
folgende Wirkung:print rc.getStr("nestedvar", expand=True) # "Ein Wert: foo" print rc.getStr("nestedvar", expand=False) # "Ein Wert: $(simplevar)" print rc.getStr("group", "var", True) # "Ein Wert: foo" print rc.getStr("group", "var", False) # "Ein Wert: $(simplevar)"
Beispiel 50.2: Verwendung des Parameters expand
(Jython script)
Das qf
Modul
In manchen Fällen ist kein Runcontext verfügbar, insbesondere wenn eines der in den
folgenden Abschnitten beschriebenen Interfaces zur Erweiterung von QF-Test implementiert
wird. Das Modul qf
ermöglicht Logging auch in diesen Fällen und bietet
weitere allgemein hilfreiche Methoden, die keinen Runcontext benötigen. Es folgt eine
alphabetische Aufstellung aller Methoden des qf
Moduls. Sofern nicht anders
angegeben sind die Methoden in Jython und Groovy sowohl für Server-Skript als
auch SUT-Skript Knoten verfügbar.
Hinweis
Die Groovy-Syntax für Keyword-Parameter unterscheidet sich von Jython. Groovy verwendet
':' statt '='. Dies ist besonders tückisch, weil z.B. qf.logMessage("bla",
report=true)
durchaus legaler Groovy-Code ist, der allerdings nicht den
gewünschten Effekt hat. Das '=' ist hierbei eine Zuweisung mit dem Wert true, der dann
ganz einfach als zweiter Parameter übergeben wird, so dass der Aufruf äquivalent ist zu
qf.logMessage("bla", true)
. Hierbei wird true aber für
dontcompactify
statt report
verwendet. Die korrekte Version
für Groovy lautet qf.logMessage("bla", report:true)
.
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3.0+50.7
Image API
Die Image API stellt Klassen und Interfaces bereit, um Bildschirmabbilder zu erstellen, Bilder in Dateien zu speichern oder zu aus Dateien zu laden. Es können auch eigene Bildvergleiche durchgeführt werden. Die Image API ist so konzipiert, dass im Allgemeinen keine Exceptions geworfen werden. Um dennoch auf mögliche Fehler eingehen zu können, werden Warnungen geloggt.
Die ImageWrapper
Klasse
Um Bildschirmabbilder zu erstellen, können Sie die Jython Klasse ImageWrapper aus dem
Modul imagewrapper.py
verwenden. Dieses Modul wird mit dem
QF-Test Installationspaket mitgeliefert.
Hier sehen Sie ein kleines Jython Beispiel, um die Verwendung der Image API darzustellen:
from imagewrapper import ImageWrapper #create ImageWrapper instance iw = ImageWrapper(rc) #take screenshot of the whole screen currentScreenshot = iw.grabScreenshot() #save screenshot to a file iw.savePng("/tmp/screenshot.png", currentScreenshot)
Das gleiche mit Groovy:
import de.qfs.ImageWrapper def iw = new ImageWrapper(rc) def currentScreenshot = iw.grabScreenshot() iw.savePng("/tmp/screenshot.png", currentScreenshot)
Es folgt eine alphabetische Aufstellung aller Methoden der
ImageWrapper
Klasse. Die verwendete Syntax ist ein
Gemisch aus Java und Python. Python unterstützt zwar selbst
keine statische Typisierung, die Parameter werden jedoch an Java
weitergereicht, so dass falsche Typen Exceptions auslösen können.
Folgt einem Parameter ein '='-Zeichen und ein Wert, ist dies der
Defaultwert des Parameters und eine Angabe beim Aufruf ist
optional.
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Das JSON
Modul
Das JSON-Modul, welches in allen Skripten ohne speziellen Import zur Verfügung steht,
bersetzt einen JSON-String in eine Datenstruktur aus Maps, Listen und primitiven Typen wie Integer,
Double, Boolean und String. Die Serialisierung geschieht über die Methode
stringify()
.
Anmerkung: Verwenden Sie rc.getJson()
, wenn Sie Daten aus einer JSON-Struktur in einer QF-Test Variable auslesen möchten.
|
|
||||||||||||||||||||||||||||||||
Sprechende Prüfausdrücke (Assertions)
Inspiriert von Chai.js haben wir eine eigene API für sprechende Asserts erstellt. Damit können Prüfausdrücke (Assertions) in einer formalisierten Sprache, die normale Wörter aus dem Englischen verwendet, formuliert werden. Sie kann in Groovy, JavaScript und Jython Skripten genutzt werden.
Motivation
Das Ziel ist, Prüfausdrücke, die in Skripten verwendet werden, besser lesbar
zu machen und auch komplexe Datenstrukturen prüfen zu können.
Aktuell geschieht die Überprüfung
von Daten in Server und SUT Skripten im Normalfall über rc.check()
oder über assert
von Java. Das funktioniert gut für Basisdatentypen
wie Zeichenketten. Es ist jedoch mühsam, komplexe Datenstrukturen wie strukturierte Objekte,
die zum Beispiel aus einem JSON-String erzeugt wurden,
damit zu prüfen. Die QF-Test Assertions API macht hier das Leben deutlich leichter.
Nachfolgend finden Sie zwei Groovy Skripte, die exemplarisch den Unterschied
zwischen sprechenden Prüfausdrücken und rc.check() beziehungsweise assert() zeigen.
def foo = 'bar'
def beverages = [ tea: [ 'chai', 'matcha', 'oolong' ] ]
expect(foo).to.be.a('String')
foo.should.be.equal('bar')
expect(foo).to.have.lengthOf(3)
expect(beverages).to.have.property('tea').with.lengthOf(3)
def foo = 'bar' def beverages = [ tea: [ 'chai', 'matcha', 'oolong' ] ] rc.check(foo instanceof String,"") rc.checkEqual(foo,'bar',"") rc.checkEqual(foo.length(),3,"") assert(beverages.tea!=null) assert(beverages.tea.size()==3)
rc.check
und Java assert
API-Dokumentation
Die QF-Test Assertions API bietet die Schnittstellen Assert
und expect
. In Groovy-Skripten
steht auch zusätzlich should
zur Verfügung. expect
und should
unterstützen Wort- bzw. Aufrufketten. Die Syntax von Assert
ist
eher die klassische Assert-Syntax wie in Java.
Das Prüfergebnis wird als erfolgreicher bzw. fehlgeschlagener Check oeder optional als Exception im Protokoll gespeichert. Zusätzlich kann das Ergebnis auch als boolescher Wert abgefragt und in einer Variable geschrieben werden. Details hierzu finden Sie in Ergebnisbehandlung.
Die API-Dokumentation steht in doc/javadoc/qfaa.zip
zur Verfügung.
Darin sind alle verfügbaren Methoden für Assert
enthalten. Diese
können ebenfalls bei expect
oder should
(in Groovy) als Teil der
Wortketten verwendet werden.
Da die QF-Test Assertions API sehr ähnlich zu Chai.js ist, funktionieren die meisten Beispiele von
https://www.chaijs.com/api/ auch in QF-Test.
Die Methoden, die in Chai.js verfügbar sind, aber noch nicht für QF-Test implementiert
wurden, sind in Abschnitt 50.9.2.3 aufgelistet.
Für Assert
kann eine Autovervollständigung mit Dokumentation der
verfügbaren Methoden aktivieren werden, indem Sie Assert.
eintippen
und anschließend Strg+Leertaste gleichzeitig drücken.
Reguläre Ausdrücke - Regexps können auch genutzt werden. Diese sind über das Modul java.util.regex.Pattern
implementiert.
Wortketten
Der größte Vorteil ist die gute Lesbarkeit, die über Wortketten erreicht wird.
Diese können bei expect()
und should()
verwendet
werden. Die folgenden Ausdrücke können aneinander gekettet werden:
.to .be .been .is .that .which .and .has .have .with .at .of .same .but
.does .still .also
def testObj = [ "name": "test", "sub": [ "name": 'test sub' ], "numbers": [1, 2, 3, 4], "hasNumbers" : true ]; expect(testObj).to.be.an('Object').and.is.ok expect(testObj).to.have.property('sub').that.is.an('Object').and.is.ok expect(testObj.sub).to.have.property('name').that.is.a('String').and.to.equal('test sub') expect(testObj).to.have.property('numbers').that.deep.equals([1, 2, 3, 4]) expect(testObj).to.have.property('hasNumbers', true)
expect
rc.setLocal("jsonData", """ { "Actors": [ { "name": "Tom Cruise", "age": 56, "Born At": "Syracuse, NY", "Birthdate": "July 3, 1962", "photo": "https://jsonformatter.org/img/tom-cruise.jpg", "wife": null, "weight": 67.5, "hasChildren": true, "hasGreyHair": false, "children": [ "Suri", "Isabella Jane", "Connor" ] }, { "name": "Robert Downey Jr.", "age": 53, "Born At": "New York City, NY", "Birthdate": "April 4, 1965", "photo": "https://jsonformatter.org/img/Robert-Downey-Jr.jpg", "wife": "Susan Downey", "weight": 77.1, "hasChildren": true, "hasGreyHair": false, "children": [ "Indio Falconer", "Avri Roel", "Exton Elias" ] } ] }""") def data = rc.getJson("jsonData") data.Actors.should.be.a("ArrayList") expect(data.Actors[0]).to.be.a("LinkedHashMap") Assert.instanceOf(data.Actors[0], "LinkedHashMap", "Bla") data.Actors[0].name.should.be.a("String") data.Actors[0].age.should.be.a("Long") data.Actors[0].weight.should.be.a("Double") data.Actors[0].hasChildren.should.be.a("Boolean") rc.setGlobalJson("gData",data)
should
Die Dokumentation hierzu finden sie in https://www.chaijs.com/api/bdd.
Unterschiede zwischen dem QF-Test Assertions API und Chai.js
Durch die Implementierung in Java ergeben sich ein paar Unterschiede zu Chai.js.
-
Weil
assert
in Java und Groovy ein reserviertes Schlüsselwort ist, muss dasAssert
von QF-Test anders (nämlich groß) geschrieben werden. Dies gilt ebenfalls für die PrüfausdrückeTRUE
,FALSE
undNULL
, welche vollständig in Großbuchstaben geschrieben werden müssen. -
Alle Methoden, die mit dem Präfix
strict
beginnen, verwenden bei Vergleichen den Gleichheitsoperator==
, ansonsten wird die Java-Methodeequal()
genutzt. Eine Liste der verfügbarenstrict
-Methoden erhalten Sie, wenn Sie im Skript-EditorAssert.strict
eintippen und anschließend Strg+Leertaste drücken. -
Assert.test
wird anstelle vonassert
verwendet.Assert.test('foo' !== 'bar', 'foo is not bar') Assert.test({true}, 'Closures can return true')
Beispiel 50.9: Assert.test(...)
Nicht verfügbare Prüfausdrücke
Einige der Prüfungen, die unter Chai.JS zu verfügung stehen, können nicht direkt von Javascript nach Java übertragen werden, und einige Assertions sind noch nicht implementiert. Dazu gehören unter anderem:
Assert
-
isAbove(), isAtLeast(), isBelow(), isAtMost()
-
isNaN(), isNotNan()
-
isUndefined()
-
isFinite()
-
throws(), doesNotThrow()
-
operator()
-
closeTo()
Expect/Should
-
.to.be.above(), .to.be.least(), .to.be.below(), .to.be.most()
-
.to.be.NaN, .not.to.be.NaN
-
.to.be.undefined
-
.to.be.finite
-
.to.throw(), .to.not.throw()
-
.to.be.closeTo()
Ergebnisbehandlung
- Ergebnisbehandlung mit Assert, expect() und should() (System)
- Server (automatisch weiter an SUT) Skript Name: OPT_PLAY_HANDLE_ASSERTION
Mögliche Werte: VAL_PLAY_HANDLE_ASSERTION_AS_CHECK, VAL_PLAY_HANDLE_ASSERTION_WITH_EXCEPTION, VAL_PLAY_HANDLE_ASSERTION_SILENTLY
Mit dieser Option beeinflusst man den Rückgabewert und die Protokollierung.
-
“Als Check behandeln” - VAL_PLAY_HANDLE_ASSERTION_AS_CHECK
Im Fehlerfall wird ein Fehler protokolliert, im Erfolgsfall ein erfolgreicher Check. -
“Als Exception” - VAL_PLAY_HANDLE_ASSERTION_WITH_EXCEPTION
Es wird im Fehlerfall eine Exception geworfen. Sie kann in Skripten als Throwable und in Try-Catch-Knoten alsScriptException
gefangen werden -
“Als Rückgabewert” - VAL_PLAY_HANDLE_ASSERTION_SILENTLY
Die Prüfung wird ausgeführt, aber nicht als Fehler gekennzeichnet. Es wird auch keine Exception geworfen. Das Ergebnis der Prüfung wird als Wert zurückgegeben, entwedertrue
oderfalse
. Wennexpect
odershould
verwendet wird, muss.getResult()
angehängt werden, um an den Rückgabewert zu gelangen. -
VAL_PLAY_HANDLE_ASSERTION_AUTOMATICALLY (Standardwert)
EntsprichtVAL_PLAY_HANDLE_ASSERTION_AS_CHECK
, außer bei der Verwendung der QF-Test Assertions API in einem Unit-Test-Knoten. Dann wird automatischVAL_PLAY_HANDLE_ASSERTION_WITH_EXCEPTION
verwendet um kompatibel mit JUnit zu sein.
-
“Als Check behandeln” - VAL_PLAY_HANDLE_ASSERTION_AS_CHECK
Die Option wird am Anfang des Skripts gesetzt:
rc.setOption(Options.OPT_PLAY_HANDLE_ASSERTION, Options.VAL_PLAY_HANDLE_ASSERTION_SILENTLY) def a = 54 def b = 55 isEqual = Assert.test(a==b, "") if (isEqual) { ... }
Wenn die Assertion in natürlicher Sprache formuliert wird, muss .getResult()
angehängt werden, um
an den Rückgabewert zu gelangen:
rc.setOption(Options.OPT_PLAY_HANDLE_ASSERTION, Options.VAL_PLAY_HANDLE_ASSERTION_SILENTLY) a = 54 b = 55 isEqual = expect(a).to.equal(b).getResult() if isEqual.getResult(): ...
Exceptions
Alle QF-Test Exceptions werden in den Skriptsprachen
automatisch importiert und stehen zum Beispiel für try/except
zur Verfügung:
try: com = rc.getComponent("someId") except ComponentNotFoundException: ...
ComponentNotFoundException
in Jython
In Groovy erfolgt dies über try/catch
:
try { com = rc.getComponent("someId") } catch (ComponentNotFoundException) { ... }
ComponentNotFoundException
in Groovy
Explizit sollten aus Skriptcode nur die folgenden Exceptions
geworfen werden (mit raise
bzw. throw new
):
-
UserException("Irgendeine Meldung...")
dient als Signal für eine außergewöhnliche Fehlersituation. -
BreakException()
oderraise BreakException("loopId")
kann dazu verwendet werden, um aus einer Schleife oder einem While Knoten auszubrechen. Die Variante ohne Parameter unterbricht die innerste Schleife, mit der QF-Test ID als Parameter kann gezielt eine bestimmte Schleife abgebrochen werden. -
ReturnException()
oderReturnException("value")
kann - mit oder ohne Rückgabewert - zur Rückkehr aus einer Prozedur verwendet werden, analog zu einem Return Knoten. Besser lesbar ist hier jedoch der Aufruf vonrc.returnValue(...)
.
Debuggen von Skripten (Jython)
Wenn Sie mit Jython-Modulen arbeiten, müssen Sie nach der Änderung
eines Moduls QF-Test oder das SUT nicht neu starten sondern können
mit Hilfe von reload(<Modulname>)
das Modul
erneut laden.
Das Debuggen von Skripten in einem eingebetteten Interpreter kann etwas mühsam sein. Um dies zu Vereinfachen bietet QF-Test Konsolenfenster für die Kommunikation mit allen Interpretern an. Informationen hierzu finden Sie am Ende des Abschnitt 11.1.
Alternativ können Sie eine Netzwerkverbindung zu einem Jython-Interpreter aufbauen, um
eine interaktive Kommandozeile zu erhalten. Dies funktioniert sowohl mit QF-Test als auch
mit dem SUT. Um dieses Feature zu aktivieren, müssen Sie QF-Test mit dem
Kommandozeilenargument -jythonport <Nummer>
starten, mit dem Sie die Portnummer für den
Zugang zum Jython-Interpreter angeben. Für das SUT definieren Sie diese mit Hilfe
eines Programm-Parameter in der "Extra" Tabelle des
Java-SUT-Client starten- oder SUT-Client starten-Knotens. Setzen Sie dieses auf
-jythonport=<Portnummer>
. Anschließend können Sie sich mittels
telnet localhost <Portnummer>
mit dem entsprechenden Jython-Interpreter verbinden. Dank Jythons Möglichkeiten zum Zugriff auf die gesamte Java-API erhalten Sie auf diesem Weg sogar eine ganz allgemeine interaktive Debugging-Schnittstelle zu Ihrer Applikation.