Funktionaler Akzeptanztest mit Bugkilla

Automatisierung von Akzeptanztests bei J2EE Web-Anwendungen

Autoren:
Andreas Spall
Orientation in Objects GmbH
Matthias Niete
Orientation in Objects GmbH
Andreas Spall
Andreas Spall
Matthias Niete
Matthias Niete
Datum:Juli 2003

Testen hat einen destruktiven Charakter.[1] Die beiden besten uns bekannten Medikamente für dieses Problem heißen "test first" und "Automatisiertes Testen". "Test first" meint bislang überwiegend, dass der Entwicklungszyklus bei Extreme Programming durch die Erstellung von Unit Tests eingeleitet wird[2]. Automatische Ausführung von Akzeptanztests ist keine Seltenheit, jedoch gelingt die Erstellung der zugehörigen Testskripte erst am fertigen System. Wir stellen mit Bugkilla einen Ansatz vor, schon am Beginn eines Entwicklungszyklus die Überführung von "User Stories" in automatisierte Akzeptanztest zu unterstützen.

Werkzeuge können dem Menschen unangenehme Tätigkeiten erleichtern bzw. sie unabhängig von ihm gestalten. Wer schon einmal eine J2EE Web-Anwendung entwickeln durfte, hat bestimmt festgestellt, wie mühsam es sein kann, diese Applikation während der Entwicklungsphase ohne Werkzeugunterstützung auf die funktionalen Gesichtspunkte hin zu überprüfen.

In vielen von uns unterstützten oder selbst durchgeführten Projekten hörte man kurz vor Release-Terminen oder Kundenpräsentationen die Worte durch die Flure schallen: "Bitte jetzt alle mal noch die nächste Zeit testen" - im besten Fall standen dabei gedruckte Testleitfäden als Textdokumente zur Klärung der Arbeitsteilung und des Vorgehens zur Verfügung. Wird die Applikation von den Entwicklern auf die funktionalen Anforderungen an das System getestet, so stellten wir häufig fest, dass die Überprüfungen sich nur auf wenige, dem Entwickler bekannte oder gerade erst entwickelte Teilbereiche beziehen. Selbst wenn es gelingt, vor einem Release-Termin einen Vertreter des Kunden vor Ort zu haben, kann auch dieser die Akzeptanztests nur manuell durchführen - oft wird er die zuvor mühsam auf Papier definierten Tests ohnehin als veraltet vorfinden.

Die XP-Praktiken „Kunde vor Ort“, „Kurze Releasezyklen“ und „Testgetriebene Entwicklung mit Akzeptanztests“, erfordern eine häufige Ausführung von teuren manuellen Akzeptanztests. Durch eine Automation dieser Test könnten die Kosten in einem Softwareentwicklungsprozess enorm gesenkt werden.

Insbesondere für Systeme mit grafischen "Rich" Clients kann man auf gute Werkzeugunterstützung zurückgreifen, einen Akzeptanztest durch den Kunden am voll integrierten System aufzuzeichnen und zu einem späteren Zeitpunkt automatisch abspielen zu lassen. Unser Versuch, für J2EE Web-Anwendungen vergleichbare Werkzeuge zu finden, die darüber hinaus auch den besonderen Spezifikationen von Web-Anwendungen Rechnung tragen, und eine solche Aufzeichnung schon auf der Basis von frühen Prototypen unterstützen, führte zum Beginn einer Eigenentwicklung namens Bugkilla, deren fachliche Idee und technischen Realisierungsstand wir hier vorstellen möchten.

Unsere fachliche Idee im Bereich der Testdokumentation orientiert sich an den etablierten Standards der IEEE 829 „Standards for Software Test Documentation“[3]. Daher werden Sie in den nachfolgenden Abschnitten mit Begriffen dieser Spezifikation konforntiert.

Die fachliche Idee von Bugkilla

Bugkilla soll die Erstellung, Pflege und Ausführung von automatisierten funktionalen Akzeptanztests für eine J2EE Web-Anwendung unterstützen. Hierbei sollen ein Vertreter des Kunden, der sogenannte Domänen-Experte, und ein Test-Ingenieur in bester XP-Kultur („Kunde vor Ort“, „test first“) mit Bugkilla an der Erstellung von automatisiert ablaufenden Systemtests arbeiten. Dies soll durch die Verwendung eines evolutionären Prototypen ermöglicht werden. Durch diese Vorgehensweise wird es für den Kunden leichter, einen Großteil seiner Anforderungen ausschließlich über "Story Cards" zu äußern, weil er für Detailfragen einfach entsprechende Akzeptanztests erstellen lassen kann.

Anforderungen an Bugkilla

Abb. 1: Anforderungen an Bugkilla

Wir möchten eine einfache Erstellung von Testfallspezifikationen durch den Kunden kombiniert mit einer möglichst werkzeugunterstützten Erstellung von ausführbaren Testprozeduren aus diesen Spezifikationen anbieten. Die Grundidee basiert auf der Aufzeichnung der HTTP-Kommunikation zwischen Browser und Web-Server. Das besondere an Web-Anwendungen (zumindest solchen, die den Browser weitgehend von Logik verschonen) ist, daß die fachliche Interaktion von Benutzer und System aufgrund des HTTP-Protokolls sehr leicht auf technische Interaktionen zwischen Client und Server abzubilden ist. Es muss nur sichergestellt werden, dass eventuell mehrere technische Anfragen an den Server, durch eine einzige User-System-Interaktion ausgelöst, später als fachlich zusammengehörig erkannt werden können.

Eine Testfallspezifikation definiert die Eingaben und Ausgaben sowie Zustandsreaktionen des System für den späteren Testfall[4]. Die Zustandsänderungen werden dabei durch die Spezifikation von Vor- und Nachbedingungen eines Tests angegeben. Eine formalisierte Erfassung der Testfallspezifikation kann für eine J2EE Web-Anwendung wie folgt abgeleitet werden: [5]

Für einen erfolgreichen Akzeptanztest   kann es von großem Interesse für den Kunden sein, dass sich das System nicht nur in seinem Ausgabeverhalten sondern auch in seinen Zustandsübergängen Spezifikationskonform verhält. So kann das Hinzufügen eines Artikels zu einem Warenkorb an der Oberfläche zwar mit einer lapidaren Erfolgsmeldung quittiert sein, Zufriedenheit wird jedoch erst aufkommen, wenn der Artikel auch "wirklich" im Warenkorb liegt. Auch dieser Überlegung soll Bugkilla Rechnung tragen.

In der Web-Schicht einer J2EE Anwendung findet sich allerdings eine große Zahl möglicher Implementierungen für jegliche fachlich interessante Funktionalität. Es stehen Servlet-, Filter-, Listener-, Hilfs-, und "Tag-Handler"-Klassen zur Laufzeit im System zur Verfügung. Zustände können auf der Ebene der Anwendung oder der Sitzung gehalten werden. Auf dem Stand der Technik unser durchgeführten Projekte schien uns jedoch für die Web-Schicht eine Beschränkung sinnvoll, die die Testbarkeit von Zustandsübergängen deutlich erhöht.

Durch den heute gebräuchlichen Einsatz von MVC-Frameworks wie etwa Struts kann von einem zentralen Controller für die Web-Anwendung ausgegangen werden. Hier bietet sich somit ein definierter Anknüpfungspunkt für die Antwort auf einige Fragen an den Zustand der Anwendung:

1.) Welches wird das nächste angezeigte Ausgabedokument sein?

2.) Welches ist die betroffene Entität eines Aufrufs in die Geschäftslogik, und welche Resultate birgt dieser Aufruf?

Der persistente Anwendungszustand lässt sich mittels grafische erzeugten JDBC-Abfragen aus einer Datenbank direkt ablesen oder bei Vorliegen einer Schicht Entity-Beans mit Container Managed Persistence am "Component Interface" der Beans ermitteln.

Die Eingaben und Ausgaben eines Testfalles lassen sich also einfach durch den Einsatz eines „Capture and Replay“ Werkzeuges aufzeichnen und ausführen. Aufzeichnungen sollten mit entsprechenden Komparatoren und Testdatengeneratoren verknüpft sein. Komperatoren ermöglichen, das Eintreten von durch Interaktion ausgelösten Zustandsübergängen mit spezifizierten Zuständen zu vergleichen. Beispielsweise kann damit überprüft werden, ob sich ein Artikel nach der Interaktion des Benutzers in einem Warenkorb befindet. Testdatengeneratoren variieren die Eingabespezifikationen eines Testfalls und kommunizieren die notwendigen Veränderungen an die Komperatoren. Ein Test-Ingenieur soll Testprozeduren aus Testfällen erstellen und nach deren Ausführung die Testprotokolle auswerten können.

Ergebnisse von Bestrebungen, die in diese Richtungen gehen, können wir jetzt noch nicht präsentieren.

Arbeitsweise mit Bugkilla

Der Einsatz von Bugkilla führt zu folgender Arbeitsweise:

In einem Testplan definiert ein Test-Ingenieur zuerst die benötigten Ressourcen, die zeitliche Planung sowie die Verantwortlichen aller Testaktivitäten eines Projekts. Darüber hinaus legt er fest, dass alle Akzeptanztests in Form von funktionalen Systemtest mit unserem Testwerkzeug Bugkilla durchgeführt werden. Welches die Testgegenstände sind und wie sie mit Bugkilla getestet werden, erläutern wir in einer Testentwurfsspezifikation.

Darauf folgend beginnt das Entwicklungsteam mit der Erstellung eines evolutionären Prototypen, auf der Basis der funktionalen Systemanforderungen (Bei uns sind diese meist durch Story Cards dokumentiert). Die nächsten Arbeitschritte erläutern das Aktivitätsdiagramm der Abb. 2.

(Abb. 2) Ausschnitt eines Softwareentwicklungszyklus mit Bugkilla

Abb. 2: Ausschnitt eines Softwareentwicklungszyklus mit Bugkilla

Mittels Bugkilla ist es dann möglich, an einem evolutionären Prototypen oder einem voll funktionsfähigen System, alle funktionalen Anforderungen des Domänen Experten aufzuzeichnen. Der Domänen Experte testet über die HTML-Oberfläche der J2EE Web-Anwendung die in der Analyse definierten Anforderungen. Diese Interaktionen des Benutzer mit dem System sollen aufgezeichnet und als sogenannte UserInteraktionen in Bugkilla dargestellt werden. Die UserInteraktionen werden von Bugkilla als Testsequenzen in eine Ablaufreihenfolge gebracht. Der Test-Ingenieur erstellt, auf der Basis von formal spezifizierten Eingabe-und Ausgabe-Regeln des Domänen-Experten, entsprechende Testdatengeneratoren und Komperatoren. Diese können dann von ihm mit den aufgezeichneten Interaktionen verknüpft werden. Dadurch entstehen aus Testsequenzen Testfälle und diese können von dem Test-Ingenieur zu Testprozeduren kombiniert werden. Mit Bugkilla ist es möglich, diese Prozeduren gegen den Prototypen auszuführen. Testprotokolle zur Auswertung der Tests werden von Bugkilla automatisch erstellt und können zu Testberichten zusammengestellt werden. Schlägt ein Test fehl, so kann es entweder an einem Fehler des getesteten System, oder an einem falsch spezifizierten Testfall liegen. Ändern sich die funktionalen Anforderungen an das System, zeichnet man neu auf. Oder passt in den bestehenden Aufzeichnungen den Akzeptanztest an. Dies muss über den gesamten Softwareentwicklungszyklus iterieren, so dass die Anforderungen und die Tests synchron miteinander bleiben.

Realisierung

Abb. 3: Capture-Funktion von Bugkilla

Abb. 3: Capture-Funktion von Bugkilla

Wir gehen davon aus, dass die "Web-Anwendung" in Form eines Prototypen schon sehr früh zur Verfügung steht. Die TestSteps einer einzelnen Interaktionen des Testers gegen den Prototypen werden vom Splitter, der als Servlet-Filter realisiert wurde, in einer UserInteraction gesammelt und an den Recorder gesendet. Als Ausprägung der Capture-Funktion von Bugkilla sammelt dieser die UserInteractions als zusammenhängende Folge in einer TestSequence und sichert diese über die Managementkomponente. Bugkilla wurde so konstruiert, daß die Speicherung dieser Daten in beliebigen Systemen vorgenommen werden kann. Bisher bieten wir im Sinne einer schnelleren manuellen Nachbearbeitung eine Implementierung an, die mit XML-Dokumenten arbeitet.

Abb. 4: Replay-Funktion von Bugkilla

Abb. 4: Replay-Funktion von Bugkilla

Der Player ermöglicht, als Replay-Funktion von Bugkilla, die Durchführung der Tests. Wir haben den Player auf der Basis des Testtreibers JUnit implementiert, um von der dafür reichhaltig vorhandenen Infrastruktur zu profitieren. Vor der Aktivierung durch das JUnit – Framework bekommt der Player die zu testende und von der Managementkomponente geladenen TestSeries übertragen. Das Framework führt nun mit Hilfe des Players die Scenarios der TestSeries aus. Für jedes Scenario muss der Player eine HTTP-Session zum Prototypen aufbauen. Auch an dieser Stelle haben wir auf eine Eigenentwicklung verzichtet und uns statt dessen für HttpUnit entschieden, das nach dem Übergeben eines Requestes die Response des Servers zurückgibt. Entdeckt ein Komparator bei der Überprüfung von Zustandsübergängen einen Fehler, beendet der Player das laufende Scenario und führt das in der TestSeries darauf folgende aus.

Bugkilla ausprobieren

Da wir sehr an Feedback oder Mitarbeit für diese Idee interessiert sind, haben wir uns entschlossen, die Entwicklung öffentlich auf sourceforge durchzuführen und von Anfang an Test-Distributionen mit einer ausführlichen Anleitung zur Inbetriebnahme bereitzustellen. Als Referenz auch für eigene Tests wurde der Petstore von SUN in seiner Original-Distribution gewählt. Somit beziehen sich unsere Anleitungen auf diese Anwendung und die J2EE-Referenzimplementierung als Standard J2EE-Application Server.

Unter unsrer Sourcefoge Projekt Seite finden sich aktuell zwei solcher Distributionen[6]. Der bugkilla-test-pack enthält eine Steuerung über Kommandozeile, die wir uns als Basis für weitere Integration in grafische Werkzeuge erhalten. Das bugkilla-eclipse-plugin ist eine Demonstration eines grafischen Front-Ends realisiert als Plug-In für Eclipse.

Das Eclipse Plug-In zeigt bereits die Steuerung des Rekorders sowie die Erstellung von Testskripten aus den Aufzeichnungen mit rudimentärer Verwaltung von Metadaten. An dieser Stelle soll noch grundlegend die Inbetriebnahme des Eclipse Plug-Ins skizziert werden. Für die eigentliche Installation empfehlen wir die der Distribution   beiliegende Dokumentation.

Installation des Eclipse Plug-Ins

Diese Distribution wurde bisher nur für Windows-Rechner getestet. Nach dem Entpacken des Downloads muss zum Installieren des Plugins das Archiv de.oio.bugkilla.eclipse.zip in das Plug-In Verzeichnis von eclipse entpackt und die IDE neu gestartet werden. Den Ablageort der aufgezeichneten Dokumente gibt man in bugkilla.properties an (default ist c:\temp). Nach dem Auswählen der Perspektive Bugkilla sollte man das Folgende sehen.

Abb. 5: Plugin Ansicht von Bugkilla

Abb. 5: Plugin Ansicht von Bugkilla

Installation des Splitters

Der als Servlet-Filter implementierte Splitter muss in der web.xml des Testlings als erster Filter eingetragen werden. Er verbindet sich beim Start der Web-Anwendung mit dem in der web.xml angegebenen Recorder. Da die Kommunikation zwischen Filter und Rekorder über eine Socket läuft, können Anpassungen in den Sicherheitseinstellungen erforderlich werden (server.policy ). Der Filter erwartet beim Start eine geöffnete Socket beim Rekorder. Deshalb muß der Rekorder vor der Web-Anwendung gestartet haben.

Aufzeichnen einer TestSequence

Die Ansicht RemoteControl bietet einen graphischen Client für den Recorder. Dieser wird über den Button „Start Server“ gestartet. Nach dem Starten des Recorders muss man den Web-Server mit der konfigurierten Web-Anwendung starten. Der Splitter baut nun eine Verbindung mit dem Recorder auf. Die Steuerbefehle an den Recorder werden jetzt an den Splitter weitergeleitet. Nun kann man eine oder mehrere TestSequences aufzuzeichnen.

Dazu übergibt man dem Recorder zunächst den Befehl „Start Sequence“. Der Befehl „Interaction“ leitet jeweils die nächste UserInteraction ein. Der nächste Request an den Web-Server wird als Beginn einer UserInteraction festgehalten. Nach der erneuten Befehlsübergabe von „Interaction“ werden die vom Splitter bis dahin gecachten Request/Response-Paare innerhalb einer UserInteraction an den Recorder gesendet und dieser fügt sie der aktuellen TestSequence hinzu. Sendet man "Stop Sequence" an den Recorder wird vom Splitter die letzte UserInteraction zum Recorder gesandt und dieser speichert die nun komplette TestSequence. Dieser TestSequence kann man innerhalb der TestSequenceView einen qualifizierenden Namen geben.

Erstellen eines Scenarios

Eine mittels „mark TestSequence“ ausgewählte TestSequence wird beim Aufruf von „new Scenario“ innerhalb der ScenarioView dem neuen Scenario hinzugefügt. Das Scenario wird in einem ScenarioPool abgelegt und kann noch durch weitere TestSequences ergänzt werden. Wie bei der TestSequence kann man dem Scenario einen qualifizierenden Namen geben.

Erstellen einer TestSeries

Ein mittels „mark Scenario“ ausgewähltes Scenario wird bei Aufruf von „new TestSeries“ innerhalb der TestSeriesView der neu erstellten TestSeries hinzugefügt. Durch die Auswahl „add Scenario“ kann man der TestSeries weitere Scenarios hinzufügen.

Abspielen einer TestSeries

Über das Aufrufen von „run TestSeries“ wird die TestSeries an das JUnit-Framework übergeben und von diesem ausgeführt. Wird bei dem Ausführen der TestSeries ein Fehler innerhalb einer TestSequence festgestellt wird das Scenario, zu dem die TestSequence gehört, beendet und das folgende Scenario der TestSeries wird zur Ausführung gebracht.

Ausblick

Wir hoffen, mit diesem Artikel Ihr Interesse für diese Idee geweckt zu haben. Sollten Sie an einer Mitarbeit interessiert sein, so bieten sich aktuell folgende Themenkomplexe an:

Dokumentenstruktur in Bugkilla

Bei der Arbeit mit Bugkilla entstehen die folgenden Dokumente:

Abb. 6: Die Dokumentenstruktur in Bugkilla

Abb. 6: Die Dokumentenstruktur in Bugkilla

Standards der Software Test Dokumentation IEEE 829

Testplan

Gemäß der Definition nach IEEE 829[3] müssen alle Aktivitäten des Qualitätsmanagements geplant werden. Als ein Ergebnis liegt ein Testplan vor. Dieser enthält Informationen über Ziele, Umfang, Methoden, Ressourcen, zeitliche Planungen sowie die Verantwortlichen. Insbesondere sollte der Testplan Auskunft über Kriterien zum Beenden bzw. Abbrechen der Tests geben.

Testentwurfsspezifikation

Eine Teilaktivität der Planung ist der Entwurf aller Tests. Dieser Entwurf wird in einer Testentwurfsspezifikation dokumentiert. Inhalte sind Aussagen über den Gegenstand sowie die Art und Weise des auszuführenden Tests. Dazu werden die zu testende Funktion oder Eigenschaft, Referenzen auf passende Anforderungs- bzw. Entwurfsdokumente sowie Hinweise zur Ermittlung konkreter Testfälle beschrieben. Außerdem werden der Ablauf und die Bedingungen der Vorbereitung, Durchführung, Protokollierung und Nachbereitung der Tests festgelegt.

Testfallspezifikation

Auf Basis der Testentwurfsspezifikation werden anschließend die Testfälle ermittelt. Die Dokumentation der Testfälle heißt Testfallspezifikation und referenziert unter anderem den Testfall eindeutig zur Testentwurfsspezifikation. Inhalt der Testfallspezifikation sind zudem Aussagen über den Testling, einzuhaltende Umgebungsvoraussetzungen sowie Abhängigkeiten des Testfalls zu anderen Testfällen. Einen wichtigen Bestandteil für die Implementierung des Testfalls stellen in der Dokumentation die spezifizierten Eingaben und Ausgaben sowie Zustandsänderungen des System für den Testfall dar. Die Zustandsänderungen werden dabei durch die Spezifikation von Vor- und Nachbedingungen eines Tests angegeben.

Testprozedur

Die Testprozedur spezifiziert die Schritte zur Ausführung einer Menge von Testfällen. Sie dokumentiert Vorschriften für die Durchführung der Tests. Eine Testprozedur verweist auf realisierte Testfälle und definiert ihre Ablaufreihenfolge. Die konkrete Form von Testprozeduren wird entscheidend durch die Form der eigentlichen Durchführung des Tests bestimmt.

Testprotokoll

Die Durchführung eines Tests anhand des jeweiligen Testskriptes wird durch ein Testprotokoll dokumentiert. Dieses Protokoll enthält außer den Informationen über den realisierten Testfall noch Angaben über Ort, Zeit und Ausführenden des Tests sowie die beobachteten Ausgaben und Zustandsübergänge des Testlings.

Testbericht

Die Testaktivitäten werden mit der Analyse der Tests fortgeführt. Dazu wird jedes Testprotokoll bewertet. Diese Bewertung erstellt ein Urteil über die Frage, ob das System nachvollziehbar im Rahmen der Erwartungen reagiert hat. Abweichungen gegenüber den Erwartungen werden als Fehler gewertet. Die Bewertung gibt also Auskunft darüber, ob ein Test fehlerfrei passiert. Zur Analyse gehört ebenfalls die Erstellung von Daten, die zur Test-Ende-Bestimmung benötigt werden. Die Testberichte werden abschließend auf erreichen des Testendes geprüft. Dazu werden die Testberichte gegen die in der Planung spezifizierten Ende- bzw. Abbruchkriterien geprüft. Der Testprozeß wird solange fortgesetzt, bis sämtliche Test-Ende-Kriterien des Testplans erreicht wurden.

Links & Literatur

Zum Geschaeftsbreich Competence Center
Schulungen
Mehr zu Code Coverage, Softwaretests und Qualitätssicherung in der Schulung automatisiertes Testen mit Java.