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.