Suche
Eine Einführung in das Jubula-Client-API

Jubula goes JUnit

Sebastian Struckmann, Markus Tiede

Image licensed by Ingram Image

Seit nunmehr zehn Jahren verfolgen wir im Jubula-Team das Ziel, Testautomatisierung für grafische Benutzeroberflächen zu ermöglichen, ohne dabei zwingend notwendig über tiefgehende Programmierkenntnisse im zugrunde liegenden UI-Toolkit oder im internen Aufbau der AUT (Application under Test) zu verfügen. Und auch auf unserem Weg zu Mars haben wir trotz der Einführung eines Java-API für Entwickler stets darauf geachtet, dieses Ziel nicht aus den Augen zu verlieren.

Unsere „Blackbox-Sicht“, aus der wir die zu testende Applikation als Ganzes von außen betrachten, spiegelt sich im Jubula-ITE (Integrated Testing Environment) seit Jahren wider. Der Fachtester beschreibt seine Testfälle mithilfe von vordefinierten Testbausteinen und eigens geschriebenen „Keyword“-Modulen in der ITE, unabhängig vom Aufbau und der Verfügbarkeit der zu testenden Applikation. Unter Zuhilfenahme von hochsprachlichen, in Jubula so genannten „Test Steps“ beschreibt der Tester kleine, mit Daten parametrisierbare Testsequenzen, die er wiederum innerhalb von wiederverwendbaren Bausteinen kapseln kann. Solche Test Steps oder auch CAPs (Component, Action, Parameter) stellen in Jubula eine auf der AUT atomar ausführbare Aktion dar und beinhalten alle zur Ausführung benötigten Informationsbestandteile:

  1. Auf welcher Componente in der Benutzeroberfläche soll
  2. welche Aktion mit
  3. welchen Parametern bzw. Daten ausgeführt werden?

Unser Ziel für das aktuelle Eclipse-Mars-Release war es, diese mächtige und über lange Zeit intern gereifte Schnittstelle zur Ausführung von CAPs für eine weitere Zielgruppe, nämlich für Java-Entwickler zu öffnen, ohne uns dabei zu sehr von den Grundprinzipien der ITE zu entfernen. Und keine Angst – ITE und API bilden in Zukunft eine Koexistenz!

Der folgende Artikel soll Einblicke in die grundlegenden Ideen (Abb. 1) des Jubula-Client-API geben und ein durchgängig nachvollziehbares Szenario am Beispiel des mittlerweile vielleicht schon berühmt-berüchtigten SimpleAdder auf RCP-Basis vorstellen.

Abb. 1: Die grundsätzliche Idee hinter dem Client-API

Abb. 1: Die grundsätzliche Idee hinter dem Client-API

Paradigmenwechsel leicht gemacht

Zeitgleich mit der Vergrößerung unseres Anwenderkreises durch die Hinzunahme von Java als Testspezifikationssprache war es uns wichtig, bei den grundlegenden Prinzipien von Jubula zu bleiben und diese, analog zur Realisierung in der ITE, auch im Client-API anzubieten:

  1. Verwendung von hochsprachlichen Testschritten (CAPs), die sich 1:1 so verhalten wie ihr Pendant in der ITE. Das Client-API bietet also analog zur ITE ebenfalls die Möglichkeit, Komponenten wie Bäume, Tabellen, Menüs, Buttons, usw. primär inhaltsbasiert anzusprechen. Ein solcher CAP lautet dabei beispielsweise „Selektiere aus dem Navigationsbaum einen Eintrag X innerhalb des Teilbaums Y/Z einmal mit der primären Maustaste“.
  2. Support für alle Toolkits. Das Client-API ist einsetzbar für alle UI-Toolkits, die auch in der ITE zur Verfügung stehen: JavaFX, AWT/Swing, SWT/RCP/GEF, iOS, HTML, Win und WinApps.
  3. Technologieübergreifende Wiederverwendung von Tests durch Nutzung einer UI-Toolkit-Abstraktionsschicht. Neben der Möglichkeit, Tests auf konkreten Toolkitimplementierungen basieren zu lassen, kann man mit dem neuen Client-API, ebenfalls analog zur ITE, unter Verwendung der Toolkitabstraktionsschicht „abstract“ und „concrete“ seine Tests für eine Ausführbarkeit auf verschiedenen UI-Toolkit-Implementierungen schreiben.
  4. Entkopplung von Testwidgets und realen AUT-UI-Komponenten: Unter Verwendung des Client-APIs kommen dieselben (exportierten) technischen „Component Identifier“ aus dem „Object Mapping“-Editor zum Einsatz. Diese werden dabei ebenfalls analog einer fachlichen Testkomponente im Quellcode zugeordnet und zum Zeitpunkt der Testausführung über denselben heuristischen Mechanismus wiedergefunden, der sich in der ITE bereits seit vielen Jahren bewährt hat.
  5. Trennung von Test- und Applikationslaufzeitumgebung: Die JVM, die zur Testausführung genutzt wird, ist unabhängig von der der AUT. Dadurch ist es möglich, Tests zu schreiben, die vom Lebenszyklus der AUT unabhängig sind. AUTs können daher problemlos erneut gestartet oder beendet werden (auch durch externe Mechanismen wie beispielsweise „autrun“). Auch die verteilte Testausführung auf verschiedenen Betriebssystemen und über Rechnergrenzen hinweg lässt sich durch die Angabe von Rechnernamen und Portnummern leicht realisieren.
  6. Der AUT-Agent verwaltet den Lebenszyklus der AUT: Die zentrale Komponente, die die Prozesse der AUT in Jubula erzeugt und überwacht, ist auch unter Verwendung des Client-APIs der sogenannte AUT-Agent.

Neben diesen gebliebenen Konzepten der ITE im Client-API gibt es einige Charakteristika, die ausschließlich im API Anwendung finden:

  1. Die minimal benötigte Java-Laufzeitumgebung für das neue Client-API ist Java SE 6.
  2. Obwohl dieser Artikel den Titel „Jubula goes JUnit“ trägt, besitzt das Jubula-Client-API in seinem Kern keine Abhängigkeit zu JUnit. Lediglich unsere Beispielszenarien nutzen diese Testausführungsumgebung. Genutzt werden kann das API aber ebenfalls in Umgebungen, die durch ein anderes Testframework wie TestNG oder Ähnliches getrieben werden.
  3. Leichtgewichtigkeit: Setzt die ITE in ihrem Kern auf OSGi und Eclipse, so ist das Client-API zwar auch in diesem Kontext problemlos einsetzbar, jedoch ebenfalls auch darüber hinaus. Zum generellen Einsatz sind neben einigen zentralen, toolkitübergreifenden noch ein paar wenige toolkitspezifische JARs notwendig. Eine genaue Auflistung findet sich in unserem „Developer Manual“ im Kapitel „General setup information“. Alles in allem beläuft sich die Menge an benötigten Abhängigkeiten auf wenige MB, was im Gegensatz zur ITE eine deutliche Verschlankung darstellt.

Aber genug der Theorie. Im Nachfolgenden wollen wir alle minimal notwendigen Schritte, die für einen ersten Start mit dem Client-API benötigt werden, im Detail vorstellen: das Verbinden zum AUT-Agenten, das Starten, Verbinden und Stoppen der AUT, das Adressieren von UI-Widgets durch das Ausführen von CAPs auf der AUT sowie das Behandeln von abweichenden AUT-Zuständen.

Step by Step: Ein RCP-SimpleAdder-Test im Detail

Damit wir eine Applikation wie den SimpleAdder als AUT starten können, benötigen wir zunächst eine Verbindung zu einem AUT Agent, dessen Zuständigkeit es ist, den Lebenszyklus der zu testenden Applikationen zu überwachen und zu steuern. Um sich mit einem AUT Agent zu verbinden, muss dieser natürlich erst gestartet werden. Dies läuft genauso ab wie bisher. Der Agent wird als Standalone-Applikation (außerhalb des APIs) ausgeführt. Erst sobald dieser Prozess läuft, ist es möglich, sich via API mit ihm zu verbinden. Unser erster Zugriff auf das API dient also dem Erstellen eines Referenzobjekts für den Agent, das wir zur Kommunikation mit ihm nutzen werden.

Ist diese erste Verbindung hergestellt, sind wir in der Lage, den Agent anzuweisen, eine oder mehrere AUTs zu starten. Dazu benötigen wir, wie aus der ITE bekannt, AUT-Konfigurationen. Diese werden nun durch schlanke, toolkitspezifische Konstruktoren im API (Abb. 2) anstelle eines umfangreichen UI-ITE-Dialogs abgebildet. Danach ist es möglich, sich in einem zweiten Schritt mit der AUT zu verbinden und mit ihr zu kommunizieren.

Abb. 2: In zwei Schritten zum Ziel: der Verbindungsaufbau zum AUT-Agent und anschließend zur AUT

Abb. 2: In zwei Schritten zum Ziel: der Verbindungsaufbau zum AUT-Agent und anschließend zur AUT

Für die Kommunikation mit der AUT existiert pro Toolkit ein Paket (OSGi-Bundle), das sämtliche toolkitspezifischen Informationen enthält, die wir benötigen, um Befehle an die AUT zu senden. Beachten müssen wir hierbei die Hierarchie unserer Toolkits: Es werden zum Beispiel für RCP auch die darüber liegenden Toolkits „SWT“, „concrete“ und „abstract“ benötigt. Diese JARs (Abb. 3) aus dem Namensraum org.eclipse.jubula.toolkit.<toolkitname>.api enthalten jeweils ein Interface und eine implementierende Klasse pro in Jubula unterstützter Komponente. Hierin enthalten ist wiederum eine Methode pro unterstütztem Aktion-/Parameter-Tupel auf dieser Komponente. In der Implementierungsklasse wird in jeder dieser Methoden ein CAP-Objekt erzeugt  und – angereichert mit allen zur Ausführung des Testschritts benötigten Informationen – zurückgegeben. Diese Objekte sind exakt dieselben, die auch in der ITE genutzt und an die AUT gesendet werden. Die AUT hat demnach nicht die geringste Ahnung, dass sie nicht mehr nur mit der ITE kommuniziert, sondern nun einen neuen zusätzlichen Auftraggeber besitzt. Mitgeteilt werden diese CAPs der AUT, auf der sie zur Ausführung kommen sollen, durch die execute()-Methode des zuvor erstellten Referenzobjekts der AUT.

Abb. 3: Beispielhafte Projektabhängigkeiten zur Nutzung des Client-APIs

Abb. 3: Beispielhafte Projektabhängigkeiten zur Nutzung des Client-APIs

Die Implementierungsklassen werden hinter Interfaces verborgen, um dem Entwickler nur das sichtbar zu machen, was er tatsächlich benutzen soll. Instanzen von ihnen erhält man mithilfe von Fabrikmethoden, die diese repräsentative Komponenten aus ComponentIdentifier-Objekten erzeugen und dabei einen Typ zurückliefern, der jeweils so abstrakt wie möglich ist, um das Paradigma von möglichst allgemeinen und wiederverwendbaren Tests aus Jubula aufrechtzuerhalten. Die hierbei benötigten ComponentIdentifier sind die einzige Stelle, die noch nicht ohne die ITE auskommt. Das Object Mapping erfolgt weiterhin auf die bisherige Weise und muss, sobald es abgeschlossen wurde, auf eine von zwei Arten aus der ITE exportiert werden. Die ComponentIdentifier aus den Mappings können sowohl in ein Properties-File (Abb. 4) als auch direkt in eine Java-Klasse exportiert werden, um dann im API benutzt zu werden. Um bessere Wartbarkeit zu gewährleisten, ist auch ein inkrementeller Export der Mappings möglich.

Abb. 4: Das Laden des aus der ITE exportierten Object Mappings

Abb. 4: Das Laden des aus der ITE exportierten Object Mappings

Auf Instanzen dieser repräsentativen Komponentenklassen hat man nun die Möglichkeit, seine Tests zu spezifizieren, und genau dies wollen wir uns nun anhand des SimpleAdder ansehen. Für unseren ersten Test nutzen wir direkt ein Konstrukt, das Jubula bisher unbekannt war: Schleifen. Eine simple For-Schleife (Abb. 5) erlaubt es uns, Jubula über mehrere Testdaten iterieren zu lassen. Dies ist in der ITE bisher nur durch explizites Angeben der Daten möglich.

Abb. 5: Das Ausführen von CAPs auf der AUT

Abb. 5: Das Ausführen von CAPs auf der AUT

Da unser SimpleAdder einen Bug (Abb. 6) besitzt, schlägt der Test bei dem letzten Iterationsschritt fehl. Die Checkaktion, die 21 als Wert erwartet, wirft nach dem Feststellen des Fehlers eine CheckFailedException (Abb. 7) aus, denn das ExecutionEvent-Verhalten aus der ITE wurde so übertragen, dass jede Art von Fehlerevent nun auf eine eigene Exception abgebildet wird, die man nach Belieben selbst behandeln oder ignorieren kann. Das eröffnet gänzlich neue Möglichkeiten.

Abb. 6: Abweichende Zustände im Soll- und Istverhalten der AUT

Abb. 6: Abweichende Zustände im Soll- und Istverhalten der AUT

Abb. 7: Exceptiones im Client-API bei Test-Execution-Problemen der AUT

Abb. 7: Exceptiones im Client-API bei Test-Execution-Problemen der AUT

Ebenso erhält man nun die vollständige Kontrolle über die Testresultate, die man nun in einem rohen Zustand als Rückgabewert eines ausgeführten CAPs auf einer AUT erhält.

Zum Abschluss unseres Tests müssen wir lediglich nur noch die AUT sauber herunterfahren und unsere Verbindung zum AUT Agent beenden (Abb. 8). Dies geschieht auf die gleiche Weise wie das Aufbauen der Verbindungen im ersten Schritt.

Abb. 8: Last but not least – das Hinterlassen eines sauberen Endzustands

Abb. 8: Last but not least – das Hinterlassen eines sauberen Endzustands

Zu guter Letzt

Wir hoffen, dieser Artikel hilft beim Einstieg in die neue Welt des Jubula-Java-Client-APIs, und freuen uns im Anschluss auf viele interessante Anregungen, Ideen und Gespräche (oder falls notwendig auch Problembeschreibungen) über

  • die Jubula Mailing List: jubula-dev@eclipse.org,
  • Einträge im Eclipse Bugzilla,
  • oder auch gerne persönlich auf einem der vielen Eclipse-Events, auf denen wir vertreten sind – bis dahin!
Geschrieben von
Sebastian Struckmann
Sebastian Struckmann
Sebastian Struckmann hat an der Technischen Universität Braunschweig Mathematik studiert und ist seit seinem Master-Abschluss im Herbst 2013 Softwareentwickler bei der BREDEX GmbH. Er beschäftigt sich dort mit RCP-Entwicklung und arbeitet im Team des Open-Source-Projekts Jubula. Aufgrund dessen ist er als Committer Teil der Eclipse-Community.
Markus Tiede
Markus Tiede
Markus Tiede arbeitet ebenfalls als Softwareentwickler und Testberater bei der BREDEX GmbH mit den Schwerpunkten auf Eclipse-RCP-Entwicklung und Design von automatisierten Regressionstests. Markus ist darüber hinaus Eclipse Committer im UI-Testautomatisierungsprojekt Jubula, Package Maintainer für „Eclipse for Testers“ und hat einen Abschluss als Diplom-Informatiker von der FH Braunschweig-Wolfenbüttel.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.