3.7. Modellansatz

In den vorherigen Kapiteln wurde bereits erwähnt, dass checkerberry web einen Modellansatz der zu testenden Webseiten verwendet. In diesem Abschnitt wird die Motivation für diesen Ansatz erläutert.

Auf der Selenium-Webseite [Selenium Homepage, 2010] wird empfohlen, das Teilprodukt Selenium IDE als Einstiegspunkt für Selenium zu verwenden. Die Selenium IDE ist ein Firefox-Plug-in, das die Interaktionen des Benutzers mit der aktiven Webseite in verschiedenen Dialekten z.B. als JUnit-Source-Code aufzeichnet. Dieser Source-Code kann als Basis für einen JUnit-Test verwendet werden. Dieser Weg führt auf lange Sicht jedoch in eine Sackgasse. Schauen wir uns dazu das vorherige Beispiel der Login-Seite auf Basis der Selenium IDE an. Die Aufzeichnung über die Selenium IDE erzeugt folgenden Source-Code:

Beispiel 3.14. Test-Aufzeichnung mit Selenium IDE

// In das Feld mit der ID userId wird der Wert ‚Homer‘ eingetragen.
selenium.type("userId", "Homer");
// In das Feld mit der ID passwordId wird der Wert ‚Duff‘ eingetragen.
selenium.type("passwordId", "Duff");
// Die Komponente mit der ID loginId wird gedrückt.
selenium.click("loginId");
// Warten auf das Laden der neuen Seite mit einem Timeout von 30.000ms.
selenium.waitForPageToLoad("30000");


Auf den ersten Blick sieht das Ergebnis ähnlich zu dem bereits geschriebenen Test aus. Als erstes fällt auf, dass in dem Test direkt die Locatoren der Komponenten (z.B. userId) verwendet werden. Das ist für sich alleine betrachtet unproblematisch. Was passiert allerdings, wenn zahlreiche Tests implementiert wurden? In dem Fall werden viele Locatoren in vielen Tests dupliziert, was große Probleme verursachen kann, wenn es Änderungen an der Webseite gibt. Die Locatoren werden innerhalb der JUnit-Tests als Strings angegeben, wobei das Refactoring von Texten in Java nur über „Suchen & Ersetzen“ möglich ist. Dieses Vorgehen birgt jedoch ein erhebliches Fehlerpotential. Das Naheliegende ist in dieser Situation die Verwendung von Konstanten: Anstatt die Locatoren direkt zu verwenden, wird für jeden Locator eine Konstante eingefügt. Das umgeht das Problem, allerdings steigt dadurch der manuelle Aufwand bei der Verwendung der Selenium IDE.

Weiterhin fällt auf, dass der Timeout von „30000“ Millisekunden hartkodiert in den Test aufgenommen wird. Auch das ist nicht wünschenswert, da dieser Wert ebenfalls zahlreich in verschiedenen Tests dupliziert wird.

Der programmierte Test verwendet die Methode clickAndWaitForPage, während dieser Aufruf bei dem aufgezeichneten Test zwei Zeilen click und waitForPageToLoad erfordert. Dieser Sachverhalt zeigt die größere Flexibilität, die der Modellansatz bietet. Das Modell kann beliebig an die Besonderheiten der zu testenden Web-Anwendung angepasst werden, indem z.B. neue Methoden erstellt werden, die generelle Aspekte zentral behandeln.

Das Login-Beispiel ist gut geeignet, um einen Einstieg in das Schreiben von automatisierten GUI-Tests zu liefern. In der Praxis sind die zu testenden Webseiten jedoch meist komplexer.

Das Login-Beispiel verwendet HTML-IDs um die Komponenten zu definieren. Das ist der beste Weg, um Selenium zu verwenden. Es kommt jedoch auch vor, dass nicht alle zu testenden Komponenten eine HTML-ID besitzen. In diesen Fällen kann der Locator XPath oder CSS-Pfade verwenden, um die Eindeutigkeit zu gewährleisten. Das Ergebnis einer Aufzeichnung sieht dann z.B. so aus:

Beispiel 3.15. Test-Aufzeichnung mit Selenium IDE und kryptischen Locatoren

// In das Feld zu dem XPath wird der Wert ‚Homer‘ eingetragen.
selenium.type("xpath=//tr/td/div/input", "Homer");
// In das Feld mit der CSS-Beschreibung wird der Wert ‚Duff‘ eingetragen.
selenium.type("css=in32", "Duff");
// Die Komponente zu dem XPath wird gedrückt.
selenium.click("xpath=//input[@value='Login']");
// Warten auf das Laden der neuen Seite mit einem Timeout von 30.000ms.
selenium.waitForPageToLoad("30000");


In dem Beispiel sieht man sehr gut, dass die Lesbarkeit der Tests stark abnimmt, wenn die Locatoren kryptisch sind. Stellen Sie sich jetzt einen umfangreichen Test mit ca. 30 Zeilen vor. Der Test ist nicht mehr lesbar und daher kaum noch wartbar. Im Gegensatz dazu werden im Modellansatz die kryptischen Locatoren in den Modellen gekapselt, sodass der Test nach wie vor lesbar bleibt.

Bei der Entwicklung von Portalen ergibt sich ein weiteres Problem, das durch die Selenium IDE nicht adressiert ist: Die HTML-IDs der Komponenten sind dynamisch!

Per Definition können in einem Portal mehrere Portlets auf einer HTML-Seite angezeigt werden – insbesondere also auch gleiche Portlets. Um die Eindeutigkeit der HTML-IDs zu gewährleisten, werden die IDs manipuliert, indem z.B. jede Portlet-Instanz ein Präfix verwendet, das vor jede HTML-ID gehängt wird. Aus der ID loginId wird so z.B. die ID P4711:loginId., wobei das Präfix P4711 dynamisch ist. Statische Locatoren können jetzt nicht mehr verwendet werden.

Der Aufzeichnungsansatz stößt spätestens hier an seine Grenzen. Da der Aufzeichnungsansatz keine Abstraktion der Locatoren verwendet, muss die erforderliche Funktionalität zur Dynamisierung der Locatoren direkt in den Tests implementiert werden. Im Modellansatz lässt sich die erforderliche Logik hingegen in den Modellklassen kapseln. Ein allgemeiner Lösungsweg ist unter Abschnitt 6.3.2, „Wie kann ich Portal-Anwendungen testen?“ beschrieben.

Die Vorteile des Modellansatzes basieren auf der guten Abstraktion der zu testenden Webanwendung. Innerhalb des Modells lässt sich generelle Funktionalität kapseln und verstecken, die sich auf alle Tests bezieht. Die Tests bleiben dadurch lesbar und wartbar.

Der Modellansatz bildet die Basis für die Entwicklung von nachhaltigen GUI-Tests. Änderungen an der Webanwendung können leicht an den Modellklassen nachgezogen werden. Änderungen von Locatoren werden direkt in den Modellklassen korrigiert. Verschiebungen von HTML-Komponenten von einer Webseite in eine andere Webseite werden ebenfalls im Modell angepasst. Dadurch entstehen Compiler-Fehler, die den Entwickler direkt zu den anzupassenden Tests führen.

Da es sich bei den Modellklassen um Java-Klassen handelt, steht dem Entwickler die gesamte Funktionalität der Entwicklungsumgebung für die Bearbeitung der Modelle zur Verfügung. Umbenennungen von Modellkomponenten werden über Refactorings durchgeführt, sodass alle Tests automatisch aktualisiert werden. Über die Navigation der Entwicklungsumgebung lassen sich schnell alle Tests auffinden, die bestimmte Komponenten oder Webseiten verwenden.

Ein weiterer Vorteil des Modellansatzes liegt in der hohen Effizienz bei der Testerstellung. Die Entwicklung der Modellklassen ist schnell, da deren Struktur sehr einfach ist. Sobald die Modelle der Webseiten vorhanden sind, kann der Entwickler die GUI-Tests wie normalen Source-Code programmieren. Der Entwickler bewegt sich somit auf vertrautem Terrain, sodass die Testerstellung sehr schnell geht.

Der Modellansatz bietet zahlreiche Vorteile im Vergleich zum Aufzeichnungsansatz. Daher verwendet checkerberry web den Modellansatz für die effiziente Erstellung von nachhaltigen GUI-Tests.

Der Modellansatz ist mittlerweile unter dem Namen Page Object Pattern [Google Page Objects, 2010] bekannt und als Best-Practice–Ansatz für GUI-Tests etabliert.