Grails und Funktionale Tests mit Geb
Dieser Beitrag stellt das Framework Geb vor, das laut Webseite [1] eine Browserautomatisierung bietet. In den meisten Fällen wird Geb für die Erstellung und Durchführung von funktionalen Tests eingesetzt.
Funktionale Tests sind so genannte Black-Box Tests [2], bei denen von außen auf das System geschaut und das externe Verhalten überprüft wird. Es werden also weder interne Strukturen noch Code überprüft. Im Bereich der Webapplikationen können hierdurch bspw. Überprüfung von Java-Skript oder Linkvalidierungen durchgeführt werden, die bei Unit- oder Integrationstests außen vor bleiben.
Wie funktioniert Geb?
Die Geb-Syntax basiert auf einer DSL [3] der Programmiersprache Groovy. Für die eigentliche Browserautomatisierung wird die WebDriver-Bibliothek eingesetzt [4], welche auch eine Kernkomponente des Test-Frameworks Selenium ist.
Unserer Erfahrung nach ist die Verwendung von Geb in Kombination mit Spock [5] empfehlenswert und gewährleistet vor allen Dingen eine "fachliche" Lesbarkeit des Codes. Hierzu tragen auch die Geb-Selektoren für Elemente von Webseiten bei, die nach dem Prinzip der jQuery-Syntax funktionieren.
Einfache Nutzung anhand eines Beispiels
Das nachfolgende Beispiel soll die einfache Nutzung von Geb verdeutlichen. Als Vorlage dient der Administrationsdialog für Caches aus der exensio E20-Plattform Claret.
Folgendes Testszenario wird hiefür aufgebaut:
- Öffnen und Validieren der Seite mit Hilfe von Selektoren
- Durchführen der Aktion zum Löschen aller Caches durch Klicken eines Links
- Validieren der wieder geladenen Seite und insbesondere Prüfung, ob die Nachricht angezeigt wird, dass alle Caches gelöscht wurden
Nachfolgend zu sehen ist die Seite nach dem Löschen der Caches.
Konfigurationsmöglichkeiten
Die exensio E20-Plattform Claret basiert auf Grails, das eine sehr gute Integration von Geb sowie auch Spock bietet. Es sei jedoch ausdrücklich erwähnt, dass Geb nicht Grails-spezifisch ist, sondern generell für Tests von Webapplikationen genutzt werden kann.
Für die Nutzung mit Grails erfolgt die Installation von Geb und Spock als Grails-Plugin in der Datei BuildConfig.groovy. Daneben ist es noch notwendig im Dependency-Block, die entsprechenden Referenzen zu WebDriver erstellen. Für weitere Informationen sei auf die Dokumentation verwiesen [6].
Erstellung des Tests
Geb unterstützt das sogenannte Page Object Pattern, bei dem Seiten als Objekte modelliert werden. Für das Beispiel wird zu diesem Zweck die Klasse CacheOverViewPage.groovy angelegt, die nachfolgend abgebildet ist.
package com.claret.pages.admin.cache
import geb.Page
class CacheOverviewPage extends Page {
static url = "cache/index"
static at = {
title == "Overview caches : Administration Center"
heading.text() == "Overview caches"
}
static content = {
heading { $('div.body h1') }
actionBar { $("div.action") }
flushAllCachesLink { actionBar.find("a") }
message(required: false) { $("div.message") }
messageAllFlushes(required: false) {
message.filter(text:contains("All caches flushed."))
}
}
}
Page-Klassen enthalten in Geb die drei Kernelemente url, at sowie content. Die Variable url definiert den relativen Pfad, unter dem die Seite erreichbar ist. Im at-Block werden Validierungen hinterlegt. In diesem Beispiel wird der Seiten-Titel überprüft und die Überschrift innerhalb der Seite. Im content-Block können über die oben bereits erwähnten Selektoren Zuweisungen zu Closures erfolgen. Beispielsweise wird die Überschrift aus einem div-Block ausgelesen. Im at-Block wird dann nur noch mit der entsprechenden Closure gearbeitet. Dies hat vor allen Dingen den Vorteil, dass bei Layout-Änderungen nur im entsprechenden content-Block Anpassungen erfolgen müssen.
Der eigentliche TestCase CacheSpec.groovy greift ebenfalls auf die Closures im content-Block zurück. Nachfolgend ist der TestCase aufgeführt und sollte weitgehend selbst erklärend sein.
package com.claret.cache
import com.claret.pages.admin.cache.CacheOverviewPage
import spock.lang.Stepwise
import com.claret.common.ClaretGebBase
@Stepwise
class CacheSpec extends ClaretGebBase {
def "flush All Cashes"() {
given: "I am at the cache page"
to CacheOverviewPage
when: "I'm clicking the flush all link"
flushAllCachesLink.click()
then: "I'm redirected to the cache page and can see the flushing message"
at CacheOverviewPage
messageAllFlushes.present
}
}
Die Spock-Notation wird zur Deklaration der einzelnen Blöcke verwendet (given, when, then) und es ist das zu Beginn beschriebene Testszenario schön nachvollziehbar. Es sei noch auf den letzten then-Block verwiesen. Dort wird die im content-Block der Page definierte Closure messageAllFlushes aufgerufen und auf ihre Existenz geprüft. D.h. es wird überprüft, ob der blaue Hinweis-Block vorhanden ist (siehe Abbildung oben).
Ausführung
Die Ausführung von Geb-Test erfolgt in Grails analog zu allen anderen Tests mit dem Kommando test-app. Zur Ausführung des konkreten TestCases ist in der Grails-Konsole das folgende Kommando einzugeben:
test-app CacheSpec
Fazit
Nach unseren Erfahrungen lassen sich mit Geb in Kombination mit Spock einfach und schnell funktionale Test erstellen. Insbesondere sind die Tests wart bar und bei Änderungen einfach anpassbar.
Es sei noch darauf hingewiesen, dass mit der vor kurzem erschienen Version 0.7.1 nun auch Geb mit Java 7 lauffähig ist, was bisher ein großes Manko war.
Links
[1] Geb Homepage
[2] Definition Back-box Testing bei Wikipedia
[3] Domain Specific Languages
[4] WebDriver
[5] Spock Homepage
[6] Geb-Integration mit Grails