05.02.2013 Aufrufe

Ausarbeitung - Institut für Wirtschaftsinformatik der WWU Münster ...

Ausarbeitung - Institut für Wirtschaftsinformatik der WWU Münster ...

Ausarbeitung - Institut für Wirtschaftsinformatik der WWU Münster ...

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

Westfälische Wilhelms-Universität <strong>Münster</strong><br />

<strong>Ausarbeitung</strong><br />

Testen von Webanwendungen mit<br />

HttpUnit und Cactus<br />

im Rahmen des Seminars „Ausgewählte Themen des Softwareengineering“<br />

Themensteller: Prof. Dr. Herbert Kuchen<br />

Betreuer: Prof. Dr. Herbert Kuchen<br />

<strong>Institut</strong> <strong>für</strong> <strong>Wirtschaftsinformatik</strong><br />

Praktische Informatik in <strong>der</strong> Wirtschaft<br />

Volker Frehe


Inhaltsverzeichnis<br />

1 Einleitung................................................................................................................... 3<br />

2 Grundlagen des Testens............................................................................................. 4<br />

2.1 Ausgewählte Arten von Testverfahren ............................................................. 4<br />

2.2 Testen mit JUnit................................................................................................ 4<br />

3 Testen von Webanwendungen................................................................................... 6<br />

3.1 Testen mit HttpUnit .......................................................................................... 6<br />

3.1.1 Aufbau einer Verbindung ............................................................................. 7<br />

3.1.2 Ausgewählte Methoden von HttpUnit zum Extrahieren von Elementen ..... 7<br />

3.1.3 Auswertung <strong>der</strong> Ergebnisse ........................................................................ 10<br />

3.2 Testen mit Jakarta Cactus ............................................................................... 12<br />

3.2.1 Generelle Funktionsweise von Jakarta Cactus............................................ 13<br />

3.2.2 Testen von Servlets..................................................................................... 14<br />

3.2.3 Testen von Servlet-Filtern .......................................................................... 15<br />

3.2.4 Testen von JSPs .......................................................................................... 16<br />

4 Zusammenfassung und Fazit ................................................................................... 17<br />

Literaturverzeichnis ........................................................................................................ 18<br />

II


Kapitel 1: Einleitung<br />

1 Einleitung<br />

Testen ist eine <strong>der</strong> wichtigsten Stufen bei <strong>der</strong> Entwicklung von Software. Fehler, die<br />

erst im fertigen Produkt aufgefunden werden, können meist gar nicht o<strong>der</strong> nur unter<br />

enormen Kosten nachträglich behoben werden. Gerade unter diesem Kostenaspekt wird<br />

dem Testen eine immer bedeuten<strong>der</strong>e Rolle zugewiesen und Ausreden wie „Ich habe<br />

keine Zeit zum Testen“ o<strong>der</strong> „Ich programmiere fehlerfrei“ sind nicht mehr akzeptabel.<br />

Somit ist das Testen nicht nur auf die reine Testabteilung beschränkt, son<strong>der</strong>n wird<br />

immer mehr in die Hände des Programmierers gelegt, um frühzeitig Fehler zu erkennen<br />

und zu beheben.<br />

Bei <strong>der</strong> Entwicklung von Webanwendungen kommt dem Testen noch eine weitere<br />

wichtige Bedeutung zu. Da die Anwendung nicht nur rein firmenintern läuft, son<strong>der</strong>n<br />

weltweit abgerufen werden kann, muss sichergestellt werden, dass die Anwendung auch<br />

auf den verschiedenen Browsern und Systemen fehlerfrei funktioniert.<br />

Um die Kosten und den Aufwand <strong>für</strong> die Tests in einem angemessenen Rahmen zu<br />

halten, bietet es sich an, die Tests nicht manuell durchzuführen, son<strong>der</strong>n hier<strong>für</strong> eine<br />

geeignete Software zu benutzen und die Tests zu automatisieren. Dies hat den Vorteil,<br />

dass zum einen die Tests wesentlicher schneller durchgeführt werden können. Des<br />

Weiteren sind die Tests so reproduzierbar und können nach einer Än<strong>der</strong>ung des Codes<br />

mit denselben Daten, welche zum Beispiel in einer Datenbank abgelegt werden, erneut<br />

ausgeführt werden.<br />

Ziel dieser Arbeit ist es, zwei Frameworks, nämlich HttpUnit und Jakarta Cactus,<br />

welche beide eine Erweiterung des Programms JUnit sind, <strong>für</strong> das Testen von<br />

Webanwendungen vorzustellen. Hierzu werden zuerst in Kapitel 2 verschiedene<br />

ausgewählte Testarten vorgestellt. Kapitel 3 enthält einen Überblick über die<br />

Funktionsweise von HttpUnit und Jakarta Cactus. In Kapitel 4 wird ein kurzer<br />

Vergleich <strong>der</strong> beiden Programme gegeben und erläutert, <strong>für</strong> welche Arten von<br />

Webanwendungen sie geeignet sind.<br />

3


Kapitel 2: Grundlagen des Testens<br />

2 Grundlagen des Testens<br />

2.1 Ausgewählte Arten von Testverfahren<br />

Das Testen von Software kann in verschiedenster Weise und zu verschiedenen<br />

Zeitpunkten <strong>der</strong> Software-Entwicklung vorgenommen werden. In Anlehnung an<br />

[KWTRF06] werden hier vier wichtige Testarten beschrieben. In Unit-Tests werden<br />

einzelne Komponenten <strong>der</strong> Anwendung, wie zum Beispiel Klassen o<strong>der</strong> Methoden,<br />

getestet. Durch Integrationstests wird anschließend geprüft, ob diese Komponenten mit<br />

dem Rest des Systems einwandfrei funktionieren. Der funktionale Test wird<br />

ausgeführt, um zu testen, ob das gesamte System entsprechend seinem<br />

Verwendungszweck einwandfrei arbeitet. Stresstests sollen das Verhalten des fertig<br />

entwickelten Systems unter starker Belastung überprüfen, um einen fehlerfreien Betrieb<br />

im Extremfall zu Gewähr leisten.<br />

Eine weitere Unterscheidung kann in so genannte Glass-Box- und Black-Box-Tests<br />

erfolgen. Bei Glass-Box-Tests ist dem Tester <strong>der</strong> komplette Quellcode bekannt,<br />

wohingegen <strong>der</strong> Tester bei Black-Box-Tests lediglich das fertige Programm und nicht<br />

den Quellcode selber sieht.<br />

Dies ist natürlich nur eine Auswahl von verschiedenen Testarten. Oft lassen sich Tests<br />

auch nicht in eine einzelne Kategorie einordnen, son<strong>der</strong>n stimmen mit mehreren<br />

Definitionen überein.<br />

2.2 Testen mit JUnit<br />

JUnit ist eine Software, um Unit-Tests <strong>für</strong> Java-Anwendungen zu schreiben. Die<br />

Testfälle sind selber in Java geschriebene Klassen, welche die zu testenden Methoden<br />

aufrufen und ihre zurück gelieferten Werte überprüfen. Diese Klassen haben alle die<br />

JUnit Klasse TestCase als Superklasse, um bestimmte bereitgestellte Methoden zum<br />

Testen benutzen und gegebenenfalls erweitern zu können.<br />

Um die zu testenden Methoden zu überprüfen, bietet JUnit einige Hilfsmethoden, die so<br />

genannten asserts, an. Die Methoden sind so aufgebaut, dass als erster (optionaler)<br />

Parameter eine Meldung angegeben wird, die bei Fehlschlag angezeigt wird. Die<br />

weiteren Parameter sind die Konditionen, die zu vergleichen sind. Eine oft benutzte<br />

4


Kapitel 2: Grundlagen des Testens<br />

assert-Methode ist assertEquals ([String message,] expexted, actual).<br />

Hiermit können die beiden Parameter expected und actual auf Übereinstimmung<br />

getestet werden. Die Methode assertTrue ([String message,] boolean<br />

condition) überprüft einen Ausdruck und gibt die Fehlermeldung aus, wenn er nicht<br />

wahr ist [Li05].<br />

Um einen Test auszuführen, müssen oft auch weitere Parameter, die nicht durch die zu<br />

testende Methode festgelegt werden, vorher auf einen bestimmten Wert festgelegt<br />

werden o<strong>der</strong> Verbindungen aufgebaut werden. Hierzu bietet JUnit die beiden Methoden<br />

setUp() und tearDown() an. Diese können in den Testklassen überschrieben werden<br />

und werden jeweils vor dem Test bzw. nach dem Test ausgeführt. Die Tests selber<br />

werden von JUnit eigenständig erkannt, sofern sie als testXXX() benannt sind [Li05].<br />

Die fertigen Testfälle werden dann mit dem JUnit TestRunner ausgeführt. Diesen gibt<br />

es zum einen als textbasierte Benutzeroberfläche, aber auch als grafische Variante. Bei<br />

<strong>der</strong> grafischen Variante wird mittels eines Balkens, entwe<strong>der</strong> rot <strong>für</strong> einen Fehlschlag<br />

o<strong>der</strong> grün <strong>für</strong> den Erfolg, das Ergebnis des Testens dargestellt. Außerdem gibt er die<br />

Fehlermeldung (wenn angegeben) aus.<br />

Abbildung 1: Erfolgreicher JUnit-Test [Ju07]<br />

5


Kapitel 3: Testen von Webanwendungen<br />

Abbildung 2: Fehlgeschlagener JUnit-Test [Ju07]<br />

Durch diese einfachen Methoden und die übersichtliche Auswertung lassen sich schnell<br />

Testfälle entwickeln, welche parallel zum zu entwickelnden Projekt ausgeführt werden<br />

und somit zu einer fehlerfreien Programmierung führen.<br />

3 Testen von Webanwendungen<br />

HttpUnit und Jakarta Cactus stellen keine eigenständige Testsoftware dar, son<strong>der</strong>n sind<br />

lediglich Erweiterungen, welche auf JUnit aufbauen. Wie schon <strong>der</strong> Name sagt, lassen<br />

sich mit JUnit Unit-Tests durchführen, was jedoch bei HttpUnit und Jakarta Cactus<br />

nicht <strong>der</strong> Fall ist. Beide Erweiterungen stellen Funktionen und Schnittstellen zur<br />

Verfügung, um Webanwendungen zu testen. Bei HttpUnit handelt es sich um (Black-<br />

Box) funktionale Tests und bei Jakarta Cactus um so genannte (White-Box)<br />

Integrations-Tests.<br />

3.1 Testen mit HttpUnit<br />

Um Webanwendungen zu testen, verfügt HttpUnit über eine API sowie diverse<br />

Methoden, um Anfragen an einen Server zu senden und Antworten von ihm zu<br />

empfangen. HttpUnit stellt somit eine Schnittstelle zwischen dem Testprogramm<br />

(JUnit) und dem Http-Protokoll dar, in dem es ausgewählte Eigenschaften eines<br />

Browsers simuliert, wodurch das Senden und Empfangen von Http-Anfragen<br />

ermöglicht wird. Des Weiteren bietet HttpUnit Methoden, um Formulare mit<br />

6


Kapitel 3: Testen von Webanwendungen<br />

entsprechenden Daten zu füllen und abzusenden, Links zu verfolgen, aber auch Cookies<br />

zu empfangen und Teile aus den zurück gelieferten Daten zu extrahieren.<br />

3.1.1 Aufbau einer Verbindung<br />

Um eine Verbindung mit dem Server aufzubauen und einen Request zu senden, wird<br />

zuerst mittels eines erzeugten WebConservation Objektes eine Sitzung gestartet. Die<br />

Klasse WebRequest enthält nun Methoden, mit <strong>der</strong>en Hilfe es möglich ist, eine Anfrage<br />

inklusive <strong>der</strong> URL zu <strong>der</strong> zu testenden Anwendung sowie die erfor<strong>der</strong>lichen Parameter<br />

an den Server zu senden. Die Antwort kann danach in einem Objekt WebResponse<br />

empfangen werden und enthält sowohl die Seite selber als auch Metadaten wie Cookies.<br />

Im folgenden Beispiel wird nun eine neue Verbindung mit dem Internet hergestellt, eine<br />

Anfrage gesendet und das Ergebnis empfangen [HOVPG04, S. 300]:<br />

WebConversation conv = new Webconversation();<br />

WebRequest req = new GetMethodWebRequest(“http://www.wi.unimuenster.de/”);<br />

WebResponse response = conv.getResponse(req);<br />

Der Code lässt sich noch weiter abkürzen, in dem man die URL direkt in den<br />

WebResponse einbaut und den WebRequest komplett weglässt:<br />

WebConversation conv = new Webconversation();<br />

WebResponse response = conv.getResponse(“http://www.wi.unimuenster.de/”);<br />

Zu beachten ist hier, dass dies lediglich eine Anfrage an den Server und Antwort von<br />

diesem ist. Eine Auswertung <strong>der</strong> zurück gelieferten Antwort findet hierbei noch nicht<br />

statt.<br />

3.1.2 Ausgewählte Methoden von HttpUnit zum Extrahieren von<br />

Elementen<br />

Zur Auswertung <strong>der</strong> zurück gelieferten Seiten stehen dem Programmierer verschiedene<br />

Klassen mit diversen Methoden zur Verfügung, um Teile aus <strong>der</strong> Antwort zu separieren<br />

und diese mit den JUnit assert-Methoden zu überprüfen.<br />

7


Kapitel 3: Testen von Webanwendungen<br />

Abbildung 3: Ausgewählte Klassen von HttpUnit [Fe04]<br />

Eine Möglichkeit ist, aus dem empfangenen Ergebnis die übermittelten Links<br />

herauszufiltern. Dies funktioniert mit getLinkWith(“string”), wobei <strong>der</strong> string <strong>der</strong><br />

klickbare Text und nicht die URL des Links ist. Zum einen kann hiermit geprüft<br />

werden, ob ein gewünschter Link auch in <strong>der</strong> Seite enthalten ist, zum an<strong>der</strong>en ist es aber<br />

auch möglich, diesen Link zu verfolgen und eine neue Anfrage mit diesem Link an den<br />

Server zu schicken. Will man zum Beispiel über eine Start-Seite zu einer<br />

weiterführenden Seite gelangen, <strong>der</strong>en Link als Text „Weitere Infos“ enthält, erreicht<br />

man dies mit folgendem Code [HOVPG04, S. 300]:<br />

WebConversation conv = new Webconversation();<br />

WebResponse response = conv.getResponse(“http://www.wi.unimuenster.de/”);<br />

WebLink link = response.getLinkWith(“Weitere Infos”);<br />

WebRequest request = link.getRequest();<br />

response = conv.getResponse(request);<br />

Da Webanwendungen meist aus Formularen bestehen, die Eingaben erfor<strong>der</strong>n, stellt<br />

HttpUnit auch Methoden bereit, um Formulardaten zum einen auszufüllen aber auch um<br />

das Formular schließlich abzuschicken. Als Beispiel sei hier eine kleine Anwendung<br />

8


Kapitel 3: Testen von Webanwendungen<br />

gezeigt, welches ein Loginscript mit Usernamen und Passwort enthält: [HOVPG04, S.<br />

302 f.]:<br />

Abbildung 4: Html-Seite mit Login-Formular<br />

WebConversation conv = new Webconversation();<br />

WebResponse response = conv.getResponse(“http://www.wi.unimuenster.de/”);<br />

WebForm form = response.getForms()[0];<br />

WebRequest loginreq = form.getRequest();<br />

loginreq.setParameter (“username”, user);<br />

loginreq.setParameter (“password”, pass);<br />

WebResponse loginresponse = conv.getResponse(loginreq);<br />

Die ersten beiden Zeilen des Codes sind bekannt. Mit Zeile drei wird nun das erste<br />

Formular <strong>der</strong> Antwort ausgewählt. Mit dem ausgewählten Formular kann man nun<br />

einen neuen Request an den Server formulieren, welches in Zeile vier geschieht. Zeile<br />

fünf und sechs weisen den Parametern username und password noch die entsprechenden<br />

Werte zu, um schließlich in Zeile sieben die Anfrage abzusenden und die Antwort zu<br />

erhalten.<br />

Während die ersten beiden Beispiele dazu dienten, von einer zur nächsten Seite zu<br />

navigieren, bietet die Klasse WebResponse auch Methoden, um Teile aus <strong>der</strong> <strong>der</strong><br />

Antwort des Servers zu extrahieren. Als Beispiel seien hier einige Methoden genannt,<br />

mit denen es möglich ist, spezielle Tabellen auszuwählen:<br />

public WebTable[] getTables()<br />

public WebTable getTableStartingWith(String text)<br />

public WebTable getTableStartingWithPrefix(String text)<br />

public WebTable getTableWithID(String text)<br />

public WebTable getTableWithSummary(String text)<br />

Es gibt noch weitere Methoden, um speziellen Content zu extrahieren. Dies kann nicht<br />

nur mit Hilfe <strong>der</strong> von HttpUnit bereit gestellten Methoden erfolgen, son<strong>der</strong>n <strong>der</strong><br />

9


Kapitel 3: Testen von Webanwendungen<br />

Programmierer selbst kann mit Hilfe <strong>der</strong> Methode getDOM() durch die Knoten einer<br />

Seite navigieren und sich spezielle Instanzen rückliefern lassen. Ermöglicht wird dieses<br />

dadurch, dass die Syntax von Webseiten dem Document Object Model (DOM) des<br />

World Wide Web Consortium unterliegt. Die bereitgestellten Methoden <strong>der</strong> Klasse<br />

WebResponse nutzen ebenfalls diese Struktur, um den Content zu extrahieren. Die<br />

Struktur des zurück gelieferten Ergebnisses ist somit wie ein Baum aufgebaut, dessen<br />

Knoten von <strong>der</strong> Wurzel an durchsucht werden können. Dies ermöglicht, bestimmte<br />

Werte (zum Beispiel alle als deklarierten Überschriften) in eine Tabelle o<strong>der</strong><br />

einen Vektor zu schreiben und somit vom Rest des Contents zu separieren.<br />

HttpUnit gibt nicht nur die Möglichkeit, Zugriff auf den Content einer Webseite zu<br />

erhalten, son<strong>der</strong>n kann auch mit Cookies arbeiten. Hier<strong>für</strong> stehen zwei Methoden <strong>der</strong><br />

Klasse WebResponse bereit, zum einen getNewCookieNames() und<br />

getNewCookieValue(). Hierdurch kann überprüft werden, ob <strong>der</strong> Server versucht,<br />

ein Cookie zu setzen und ob die Werte, die das Cookie zu setzen versucht, die Richtigen<br />

sind.<br />

3.1.3 Auswertung <strong>der</strong> Ergebnisse<br />

Alleine das Separieren von Teilen <strong>der</strong> übermittelten Seite sagt natürlich noch nichts<br />

über die Korrektheit <strong>der</strong> Daten aus. Hierzu müssen die empfangenen dann mit den<br />

erwarteten Daten verglichen werden. Bedenkt man, dass jede einzelne Seite einer<br />

Webanwendung an<strong>der</strong>s ist, müsste man hier im Grunde <strong>für</strong> jede eine eigene Testklasse<br />

schreiben. Der Aufwand hier<strong>für</strong> ist allerdings größer als <strong>der</strong> daraus erzielte Nutzen. Aus<br />

diesem Grund werden Testfälle nur <strong>für</strong> Seiten geschrieben, bei denen <strong>der</strong> manuelle<br />

Aufwand des Testens größer ist als <strong>der</strong> Aufwand des Schreibens eines Testfalls <strong>für</strong> die<br />

Anwendung. Ein denkbarer Fall hier<strong>für</strong> ist zum Beispiel ein Formular mit mehreren<br />

Eingabemöglichkeiten und daraus resultierenden verschiedenen Ergebnissen. Hier<br />

durchläuft das Testprogramm dann eine Tabelle mit den möglichen Eingaben und<br />

vergleicht die zurück gelieferten Ergebnisse mit den ebenfalls in <strong>der</strong> Tabelle<br />

gespeicherten richtigen Ergebnissen. Auch wenn dies bei einem einmaligen Test den<br />

gleichen Aufwand wie bei einem manuellen Test aufweist, so reduziert sich <strong>der</strong><br />

Aufwand schon, wenn man ein zweites Mal testet, nachdem sich zum Beispiel etwas an<br />

<strong>der</strong> Seite geän<strong>der</strong>t hat. Da <strong>der</strong> Test selber nicht geän<strong>der</strong>t werden muss, kann er erneut<br />

wie<strong>der</strong> eingesetzt werden.<br />

10


Kapitel 3: Testen von Webanwendungen<br />

Ein Beispiel hier<strong>für</strong> ist das oben genannte Login-Formular. Erscheint nach dem Login<br />

eine Seite mit dem Titel „Login erfolgt“, kann durch einfaches Testen geprüft werden,<br />

ob <strong>der</strong> Login erfolgreich war:<br />

WebConversation conv = new Webconversation();<br />

WebResponse response = conv.getResponse(“http://www.wi.unimuenster.de/”);<br />

WebForm form = response.getForms()[0];<br />

WebRequest loginreq = form.getRequest();<br />

loginreq.setParameter (“username”, user);<br />

loginreq.setParameter (“password”, pass);<br />

WebResponse loginresponse = conv.getResponse(loginreq)<br />

assertEquals (“Login erfolgt”, loginresponse.getTitle());<br />

Hier wurde nun einfach geprüft, ob <strong>der</strong> Titel <strong>der</strong> empfangenen Seite mit dem erwarten<br />

übereinstimmt. Sollte dies <strong>der</strong> Fall sein, erscheint im JUnit TestRunner ein grüner<br />

Balken und <strong>der</strong> Test wurde erfolgreich ausgeführt. Schlägt <strong>der</strong> Vergleich fehl, so wird<br />

<strong>der</strong> Balken im TestRunner rot und <strong>der</strong> Fehler wird ausgeliefert.<br />

Ein weiterer möglicher Einsatz ist das Schreiben eines Tests, welcher Gegebenheiten<br />

testet, die auf verschiedene Seiten zutreffen. So ist laut [HOVPG04] das Testen aller<br />

Links auf einer Seite und aller weiterführenden Links mit einer einfachen Testklasse<br />

möglich:<br />

private WebConversation conversation;<br />

private Set checkedlinks;<br />

private String host = www.uni-muenster.de;<br />

public void setUp(){<br />

conversation = new WebConversation();<br />

checkedLinks = new HashSet();<br />

}<br />

public void testEntireSite() throws Exception{<br />

WebResponde response =<br />

conversation.getResponse(“http://”+host);<br />

checkAllLinks(response);<br />

System.out.prinln(“Alle Links überprüft”);<br />

}<br />

private void checkAllLinks (WebResponse response) throws<br />

Exception{<br />

if(!isHtml(response))return;<br />

WebLink[] links = response.getLinks();<br />

for(int i = 0; i < links.length; i++){<br />

boolean newLink = checkedLinks.add(links[i].getURLString());<br />

if(newLink){<br />

checkLink(links[i]);<br />

}<br />

}<br />

}<br />

11


Kapitel 3: Testen von Webanwendungen<br />

private boolean isHtml(WebResponse response){<br />

return response.getContentType().equals(“text/html);<br />

}<br />

private void checkLink(WebLink link) trhows Exception{<br />

WebRequest request = link.getRequest();<br />

java.net.URL url = request.getURL();<br />

String linkHost = url.getHost();<br />

if(linkHost.equals(this.host)){<br />

WebResponse response = conversation.getResponse(request);<br />

this.checkAllLinks(response);<br />

}<br />

}<br />

Zuerst wird hier wie<strong>der</strong> mit setUp() eine Verbindung mit einem Server aufgebaut und<br />

ein Hashset <strong>für</strong> die zu überprüfenden Links bereitgestellt. Mit testEntireSite()<br />

wird nun eine Anfrage an <strong>der</strong> Server gestellt und danach checkAllLinks()<br />

aufgerufen. Die Methode checkAllLinks() ruft zuerst isHtml() auf, um zu<br />

überprüfen, ob es sich auch um eine (auswertbare) Html-Seite handelt. Sollte dies <strong>der</strong><br />

Fall sein, werden alle in <strong>der</strong> Seite enthaltenen Links in ein Array geschrieben. Dieses<br />

Array wird nun durchwan<strong>der</strong>t und <strong>für</strong> jeden Eintrag die Methode checkLink()<br />

aufgerufen. Hier wird nun überprüft, ob es sich um einen internen o<strong>der</strong> externen Link<br />

handelt. Externe werden nicht überprüft, da sie nicht zum eigenen Projekt gehören.<br />

Handelt es sich um einen internen Link, wird <strong>für</strong> diesen Link ein Request durchgeführt.<br />

Wird dabei ein ungültiges Ergebnis zurückgeliefert, so handelt es sich um einen<br />

defekten Link und die Exception wird ausgelöst, die wie<strong>der</strong> im JUnit TestRunner<br />

ausgegeben wird. Da rekursiv alle Links <strong>der</strong> Webseite überprüft werden, können so alle<br />

fehlerhaften Links entdeckt werden. Um ein an<strong>der</strong>es Projekt zu testen, muss lediglich<br />

<strong>der</strong> Host geän<strong>der</strong>t werden. Dies ist nur ein kleiner Testfall, <strong>der</strong> sich lediglich auf<br />

statische Inhalte anwenden lässt, da dynamische Seiten und Formulare ignoriert werden.<br />

3.2 Testen mit Jakarta Cactus<br />

Im Gegensatz zu HttpUnit, bei dem funktionale Tests von Webseiten durchgeführt<br />

wurden, werden bei Jakarta Cactus Integrations-Tests durchgeführt. Cactus stellt hierzu<br />

drei Unterklassen bereit, um serverseitigen Java-Code zu testen. Hiermit ist es möglich,<br />

Servlets [HOVPG04, S. S. 361], JSPs [HOVPG04, S. 371] und Servlet Filter<br />

[HOVPG04, S.365] zu testen. Weiterhin ermöglicht es, EJBs [HOVPG04, S. 394] mit<br />

Cactus zu testen. Da dies aber keine spezielle Technik nur <strong>für</strong> Webanwendungen<br />

darstellt, wird dies in dieser Arbeit nicht betrachtet.<br />

12


Kapitel 3: Testen von Webanwendungen<br />

3.2.1 Generelle Funktionsweise von Jakarta Cactus<br />

Die Beson<strong>der</strong>heit bei Cactus ist, dass zwei Testfälle erzeugt werden, zum einen auf <strong>der</strong><br />

Clientseite, zum an<strong>der</strong>en auf <strong>der</strong> Serverseite.<br />

Abbildung 5: Ausführung eines Cactus-Tests [Ja07]<br />

Der JUnit Test Runner führt den Test zunächst auf <strong>der</strong> Clientseite aus. Hierzu wird die<br />

Methode runTest() ausgeführt. Für jede testXXX() Methode wird nun nach einem<br />

beginXXX() gesucht. In beginXXX() können auch weitere Parameter gesetzt werden,<br />

welche zur Ausführung des serverseitigen Codes notwendig sind. (1)<br />

Anschließend wird eine Verbindung mit einem Redirector aufgebaut und <strong>der</strong> Request,<br />

mit allen ihm übergebenen Parametern, wird an ihn gesendet. (2)<br />

Der Redirector fungiert auf Serverseite wie <strong>der</strong> JUnit Test Runner auf <strong>der</strong> Client Seite.<br />

Hierzu wird <strong>der</strong> Redirector initialisiert und bekommt alle Parameter <strong>für</strong> die<br />

Testausführung übergeben. (3)<br />

Nach <strong>der</strong> Initialisierung führt <strong>der</strong> Redirector nacheinan<strong>der</strong> die Methoden setUp(),<br />

testXXX() und tearDown() aus. (4)<br />

Bei <strong>der</strong> Ausführung <strong>der</strong> testXXX()-Methode werden <strong>der</strong> serverseitige Java-Code (JSP,<br />

Servlet o<strong>der</strong> Servlet Filter) ausgeführt und JUnit Methoden zum Auswerten <strong>der</strong><br />

Ergebnisse benutzt. (5)<br />

Die Ergebnisse des Tests (egal ob erfolgreich o<strong>der</strong> misslungen) werden vom Redirector<br />

eingesammelt. (6)<br />

Sind alle Tests ausgeführt, schickt <strong>der</strong> Redirector die Ergebnisse zurück zum Client. (7)<br />

13


Kapitel 3: Testen von Webanwendungen<br />

Wurden Fehler bei <strong>der</strong> Ausführung <strong>der</strong> Tests gefunden, so werden diese nun im JUnit<br />

Test Runner angezeigt. Wurden keine Fehler gefunden, sucht runTest() nun nach<br />

einem endXXX() und führt es aus. Hierbei ist es erneut möglich, die empfangenen<br />

Daten mit JUnit zu überprüfen.<br />

3.2.2 Testen von Servlets<br />

Servlets stellen Java-Klassen dar, die Http-Anfragen entgegennehmen und diese<br />

beantworten. Dabei kann je nach Parameter <strong>der</strong> Inhalt dynamisch erzeugt werden.<br />

Jakarta Cactus stellt hier<strong>für</strong> eine junit.framework.TestCase Unterklasse bereit:<br />

org.apache.cactus.SevletTestCase<br />

Um einen Testfall zu generieren, muss <strong>der</strong> Programmier drei Methoden erzeugen<br />

(beginXXX(), testXXX() und endXXX()). Außerdem muss in <strong>der</strong> web.xml (einer<br />

Datei, die bei <strong>der</strong> Installation von Cactus auf den Server gelegt wird) ein Eintrag<br />

vorgenommen werden, damit <strong>der</strong> Testfall den entsprechenden Redirector <strong>für</strong> Servlets<br />

benutzt [HOVPG04, S. 361]:<br />

<br />

ServletRedirector<br />

<br />

org.apache.cactus.server.ServletTestRedirector<br />

<br />

<br />

<br />

ServletRedirector<br />

/ServletRedirector<br />

<br />

Mit <strong>der</strong> Methode beginXXX() wird eine Verbindung mit dem Server hergestellt. Ihm<br />

werden zum einen die URL <strong>der</strong> zu testenden Seite übergeben als auch notwendige<br />

Parameter zur Initialisierung. Des Weiteren können zum Beispiel noch Cookies <strong>für</strong> den<br />

Request gesetzt werden [Ja07]:<br />

public void beginXXX(WebRequest theRequest){<br />

theRequest.setURL("uni-muenster.de", "/app", "/test.jsp", null,<br />

null);<br />

theRequest.addCookie("cookiename", "cookievalue");<br />

}<br />

Cactus erstellt automatisch ein WebRequest Objekt und stellt es unter den Namen<br />

„response“ den Methoden setup(), testXXX() und teardown() bereit. Dieses<br />

Objekt verweist auf das in beginXXX() erstellte WebRequest Objekt. In <strong>der</strong><br />

14


Kapitel 3: Testen von Webanwendungen<br />

testXXX()-Methode wird nun das eigentliche Servlet getestet. Mit <strong>der</strong> Funktion<br />

assertEquals() kann zum Beispiel <strong>der</strong> Inhalt von Attributen auf Übereinstimmung<br />

überprüft werden [Ja07]:<br />

public void testXXX(){<br />

MyServletToTest servlet = new MyServletToTest();<br />

servlet.init(config);<br />

servlet.methodToTest();<br />

assertEquals("someValue",<br />

session.getAttribute("someAttribute"));<br />

assertEquals("uni-muenster.de", request.getServerName());<br />

}<br />

Das zurück gelieferte Ergebnis kann nun noch in <strong>der</strong> endXXX()-Methode ausgewertet<br />

werden. Hier kann wie<strong>der</strong>um ähnlich wie bei HttpUnit zum einen auf den Content des<br />

Ergebnisses als auch auf MetaDaten und Cookies zugegriffen werden [Ja07]:<br />

public void endXXX(WebResponse theResponse){<br />

Cookie cookie = theResponse.getCookie("someCookie");<br />

assertEquals("someValue2", cookie.getValue());<br />

assertEquals("some content here", theResponse.getText());<br />

}<br />

3.2.3 Testen von Servlet-Filtern<br />

Servlet-Filter dienen dazu, vor und/o<strong>der</strong> nach dem Zugriff auf ein Servlet Informationen<br />

dem Servlet hinzuzufügen o<strong>der</strong> Informationen herauszufiltern und diese zum Beispiel<br />

auf dem Server abzulegen. Um diese Filter zu testen, muss wie<strong>der</strong> eine spezielle<br />

Testklasse eingebunden werden:<br />

org.apache.cactus.FilterTestCase<br />

Auch hier muss dem Programm mittels Eintrag in <strong>der</strong> web.xml mitgeteilt werden,<br />

welcher Redirector verwendet wird:<br />

<br />

FilterRedirector<br />

<br />

org.apache.cactus.server.FilterTestRedirector<br />

<br />

<br />

<br />

FilterRedirector<br />

/FilterRedirector<br />

<br />

Jetzt kann <strong>der</strong> eigentliche Test geschrieben werden. Die beginXXX()-Methode<br />

funktioniert wie oben beschrieben und beschreibt lediglich den Request an eine Seite.<br />

15


Kapitel 3: Testen von Webanwendungen<br />

Mit <strong>der</strong> testXXX()-Methode kann nun ein Filter auf einen Response ausgeführt<br />

werden. Im folgenden Beispiel wird ein Hea<strong>der</strong> und ein Footer dem Response zugefügt<br />

[Ja07]:<br />

public void testXXX() throws ServletException, IOException{<br />

SampleFilter filter = new SampleFilter();<br />

config.setInitParameter("hea<strong>der</strong>", "Kopf");<br />

config.setInitParameter("footer", "Fuss");<br />

filter.init(config);<br />

FilterChain mockFilterChain = new FilterChain() {<br />

public void doFilter(ServletRequest theRequest,<br />

ServletResponse theResponse) throws IOException,<br />

ServletException{<br />

PrintWriter writer = theResponse.getWriter();<br />

writer.print("Inhalt");<br />

writer.close();<br />

}<br />

public void init(FilterConfig theConfig){<br />

}<br />

public void destroy(){<br />

}<br />

};<br />

filter.doFilter(request, response, mockFilterChain);<br />

}<br />

Hier wird nun zuerst <strong>der</strong> Filter initialisiert, die Parameter <strong>für</strong> den Footer und Hea<strong>der</strong><br />

gesetzt und dann <strong>der</strong> Filter ausgeführt. Um zu testen, ob das zurück gelieferte Ergebnis<br />

auch wirklich den Footer sowie den Hea<strong>der</strong> enthält, kann wie<strong>der</strong> die endXXX()-<br />

Methode benutzt werden [Ja07]:<br />

public void endXXX(WebResponse theResponse){<br />

assertEquals("hea<strong>der</strong>some<br />

contentfooter", theResponse.getText());<br />

}<br />

Abschließend wird lediglich noch geschaut, ob die Informationen, die <strong>der</strong> Filter dem<br />

Response hinzugefügt hat, auch vorhanden sind.<br />

3.2.4 Testen von JSPs<br />

JavaServer Pages (JSP) ist eine Technologie, die es erlaubt, Java-Code in statische<br />

Inhalte einzubetten. Hierdurch ist es möglich, dass Inhalt und Design getrennt<br />

voneinan<strong>der</strong> behandelt werden und mittels <strong>der</strong> JSPs dynamische Inhalte eingebunden<br />

werden. Eine Einbindung <strong>der</strong> entsprechenden Testklasse ist obligatorisch:<br />

org.apache.cactus.JspTestCase<br />

16


Kapitel 4: Zusammenfassung und Fazit<br />

Um hier wie<strong>der</strong> dem Testfall einen Redirector zuzuweisen, muss dieser auf bekannte<br />

Weise in die web.xml eingetragen werden.<br />

Das Testen von JSPs beschränkt sich jedoch auf den Test <strong>der</strong> zurück gelieferten Seiten<br />

(zum Beispiel HTML o<strong>der</strong> XML). Man stellt im Grunde lediglich eine Anfrage an diese<br />

Seite mit dem integrierten JSP und übergibt die benötigten Parameter:<br />

Danach kann wie<strong>der</strong> auf Client-Seite die Antwort mit endXXX() ausgewertet werden.<br />

Da das zurück gelieferte Ergebnis einer „normalen“ Internetseite entspricht, können hier<br />

wie<strong>der</strong> von JUnit bereit gestellte Methoden verwendet werden, um das Ergebnis<br />

auszuwerten.<br />

4 Zusammenfassung und Fazit<br />

Mit HttpUnit und Jakarta Cactus werden zwei unterschiedliche Erweiterungen <strong>für</strong> JUnit<br />

bereitgestellt. Während mit HttpUnit funktionale Tests von Webanwendungen<br />

durchgeführt werden, bietet Jakarta Cactus die Möglichkeit, Integrationstests <strong>für</strong><br />

serverseitige Java-Anwendungen durchzuführen.<br />

Durch immer komplexer werdende Webanwendungen ist hier, wie auch in den an<strong>der</strong>en<br />

Bereichen des Software Engineering, ein Testen des erstellten Codes <strong>für</strong> eine<br />

komplikationslose Entwicklung erfor<strong>der</strong>lich. Auf Grund <strong>der</strong> Simplizität <strong>der</strong><br />

bereitgestellten Methoden lassen sich schnell Testfälle entwickeln, um<br />

Webanwendungen während <strong>der</strong> Entwicklung auf einwandfreie Funktion zu überprüfen.<br />

Da die beiden Erweiterungen unterschiedliche Teile <strong>der</strong> Webanwendung testen und<br />

somit unterschiedliche Tests durchführen, gibt es keine Bevorzugung einer Erweiterung.<br />

Vielmehr braucht man <strong>für</strong> größere Projekte sowohl Jakarta Cactus als auch HttpUnit,<br />

um die Anwendungen komplett zu testen. Um die Tests noch unkomplizierter zu<br />

gestalten, bietet Jakarta bei seinem Cactus Projekt mittlerweile die Integration von<br />

HttpUnit an.<br />

Durch beide Erweiterungen besteht die Möglichkeit, manuelle Tests abzulösen und das<br />

Testen wesentlich effizienter zu gestalten. Die Zeitersparnis auf Grund des Testens lässt<br />

sich somit in an<strong>der</strong>e Bereiche <strong>der</strong> Entwicklung Nutzen bringend einsetzen und steigert<br />

hierdurch die Qualität des Endproduktes.<br />

17


Literaturverzeichnis<br />

[Fe04] Balazs Fejes, Test Web applications with HttpUnit,<br />

http://www.javaworld.com/javaworld/jw-04-2004/jw-0419httpunit.html?page=1,<br />

2004, Abrufdatum: 2007-04-18.<br />

[HOVPG04] Richard Hightower, Warner Onstine, Paul Visan, Damon Payne, Joseph<br />

D. Gradecki: Java Tools for extreme Programming, Wiley Publishing, 2004.<br />

[Ja07] The Jakarta Projekt: Jakarta Cactus, http://jakarta.apache.org/cactus/,<br />

Abrufdatum: 2007-04-20.<br />

[Ju07] JUnit.org: JUnit, Testing Ressources for Extreme Programming,<br />

http://www.junit.org/. Abrufdatum: 2007-05-10.<br />

[KWTRF06] Axel Kalenborn, Thomas Will, Rouven Thimm, Jana Raab, Ronny<br />

Fregin: Java-basiertes automatisiertes Test-Framework,<br />

<strong>Wirtschaftsinformatik</strong> 48 (2006), S.437-445.<br />

[Li05] Johannes Link: Softwaretests mit JUnit, dpunkt.verlag, 2005.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!