Wenn es um die Entwicklung einer SOAP-Schnittstelle geht kommt man an SoapUI von SmartBear kaum vorbei. Das Tool bietet in der kostenlosen Version wenig Komfort erlaubt aber trotzdem mit ein wenig Geschick und Hintergrundwissen die Erstellung komplexer Testszenarien. Dank des von der Konsole ansprechbaren testrunners und dem Export der Ergebnisse als XUnit-Report lässt sich SoapUI gut in CI-Umgebungen wie Jenkins integrieren.
Die folgenden Beispiele stammen aus einem Kunden-Projekt bei dem es um Autovermietung geht und sind so mit Version 4.6.4 umgesetzt.
Eine sehr kurze Einführung in SoapUI
Da es an dieser Stelle nicht darum geht, wie SoapUI allgemein funktioniert, gebe ich für die grundlegenden Schritte keine Beispiele oder ähnliches an. Die Grundlagen von SoapUI sind schnell gelernt.
Am Anfang war das Wort die WSDL
Zu Beginn eines neuen Test-Projekts steht der Import der WSDL zur Schnittstelle. SoapUI erstellt für jede Operation einen Eintrag und erlaubt es, mehr oder weniger komfortabel, einen Request zu erstellen. Die Ausgabe wird formatiert in einem zweiten Fenster dargestellt. So weit, so einfach. Für einen schnellen Test, ob die Schnittstelle funktioniert, reicht das aus.
Testen für Anfänger
Um wirklich zu Testen muss eine Test Suite erstellt werden. Eine Test Suite besteht aus beliebig vielen Test Cases und diese wiederum aus beliebig vielen Test Steps. Ein normaler Step besteht aus einer Anfrage an die Schnittstelle sowie Bedingungen, wann der Test als erfolgreich gilt (sog. Assertions). So ist es möglich, für jede Operation Test Cases zu schreiben und in den Test Stept verschiedene Varianten (erfolgreiche Abfragen, gewollte Faults etc.) durch zu spielen. Die folgende Anfrage meldet einen Kunden im System an.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="testkunde.de/namespace"> <soapenv:Header/> <soapenv:Body> <Api.login> <login> <technicalUser> <username>user</username> <password>pass</password> </technicalUser> <customer> <membershipNoAndPassword> <membershipNo>1234567890</membershipNo> <password>geheim</password> </membershipNoAndPassword> </customer> </login> </Api.login> </soapenv:Body> </soapenv:Envelope>
In diesem und dem folgenden Request zeigen sich die ersten Probleme, wenn die Tests komplett von Hand geschrieben werden:
Wir kommen in diesem Kundenprojekt inzwischen auf deutlich über 100 Tests für die SOAP-Schnittstelle. Bei einer großen Anzahl von Tests kann es sehr lästig werden, immer wieder und wieder die gleichen Daten einzugeben. Copy-Paste mag da am Anfang noch eine Lösung sein – spätestens wenn die Zugangsdaten des Testnutzers sich mal ändern wird es hässlich.
Zum Anderen erlauben alle weiteren Operationen in der SOAP-API des Kunden keinen Login mit Kundennummer und Passwort. Statt dessen wird ein temporärer Schlüssel erwartet, der beim Login generiert wird. Dieser verfällt nach 15 Minuten Inaktivität und müsste sehr schnell in alle folgenden Anfragen einkopiert werden…
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="testkunde.de/namespace"> <soapenv:Header/> <soapenv:Body> <Api.getCustomer> <getCustomer> <technicalUser> <username>user</username> <password>pass</password> </technicalUser> <authKey>???</authKey> </getCustomer> </Api.getCustomer> </soapenv:Body> </soapenv:Envelope>
Es wird Zeit, ernst zu machen.
Komplexe Tests mit SoapUI
When the going gets tough, the tough get going.Joseph P. Kennedy
SoapUI bietet zum Glück Möglichkeiten, die oben angesprochenen Probleme zu lösen: Custom Properties und Property Transfer.
Testen für Fortgeschrittene
Wählt man im Navigationsbaum eine Suite, einen Case oder einen Step aus, dann gibt es unten links einen recht unauffälligen Karteireiter „Custom Properties“. In diesem können beliebig viele Schlüssel-Wert-Paare angelegt werden. Die die beiden Beispiele oben sehen dann schon anderes aus.
Verwendung von Custom Properties
Mit ${} greift man auf die Custom Properties innerhalb einer Anfrage zu. #TestSuite, #TestCase und #TestStep referenzieren dabei den Kontext, gefolgt von #name.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="testkunde.de/namespace"> <soapenv:Header/> <soapenv:Body> <Api.login> <login> <technicalUser> <username>${#TestSuite#t_user}</username> <password>${#TestSuite#t_passwd}</password> </technicalUser> <customer> <membershipNoAndPassword> <membershipNo>${#TestSuite#customerNumber}</membershipNo> <password>${#TestSuite#customerPassword}</password> </membershipNoAndPassword> </customer> </login> </Api.login> </soapenv:Body> </soapenv:Envelope>
Auch beim Abrufen der Kundendaten verwenden wir den gespeicherten temporären Schlüssel aus der Login-Operation.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="testkunde.de/namespace"> <soapenv:Header/> <soapenv:Body> <Api.getCustomer> <getCustomer> <technicalUser> <username>${#TestSuite#t_user}</username> <password>${#TestSuite#t_passwd}</password> </technicalUser> <authKey>${#TestSuite#customerAuthKey}</authKey> </getCustomer> </Api.getCustomer> </soapenv:Body> </soapenv:Envelope>
Aber wie kommt der Wert des Schlüssels aus der Antwort in die Custom Property?
Übertragen von Eigenschaften
Neben den normalen Test Steps gibt es noch diverse weitere, darunter Property Transfer. Wir würden unserem Case als nach dem ersten Step (Test Request) einen zweiten hinzufügen. Ein Property Transfer Step kann aus mehreren Transfers bestehen. In unserem Fall ist die Quelle der vorhergehende Step ‚GetAuthKey‘ bzw. dessen ‚Response‘, also die Antwort im XML-Format. Mit einem einfachen XPath Ausdruck wird das entsprechende Element (<loginResponse><login><authKey>) gewählt. Ziel des Transfers ist die Eigenschaft customerAuthKey der Suite. Voilà – der Wert steht von nun an allen weiteren Tests zur Verfügung.
Testen für Profis
Als Sahnehäubchen bietet SoapUI mit dem Test Step Typ „Run TestCase“ die Möglichkeit, Test Cases innerhalb anderer Cases zu referenzieren und diesen wiederum Werte mitzugeben. Auf diese Weise können diese Cases ähnlich wie Funktionen in Programmiersprachen wiederverwendet werden.
So haben wir in unseren Tests z.B. einen Test Case definiert, der über die Schnittstelle Vorschläge für buchbare Fahrzeuge abfragt und die UID des ersten Fahrzeugs als Property des Run Steps zurück gibt. Hierfür muss im Run TestCase Step das Werkzeug-Symbol geklickt werden (rot eingekreist). Es öffnet sich ein weiteres Fenster. Im zweiten Fenster wählt man Suite und Case aus. Der Run Case selbst hat automatisch die gleichen Custom Properties wie das Ziel, so dass diese mit einem Transfer gefüllt werden können. Die Custom Properties des Zieles können dann entweder nur geschrieben oder nach dem Aufruf als Return Property wieder ausgelesen werden (hier die vehicleId). Nicht einfach aber sehr elegant.
Achtung! Die „Funktions-Cases“ sollten deaktiviert werden, da SoapUI sie sonst wie alle anderen Cases natürlich auch ausführt, was häufig nicht sinnvoll ist.
Happy Testing!