Automatisiertes Testen von Webseiten mit dem Selenium WebDriver

Das Open Source Projekt „Selenium“ zum Durchführen automatisierter Browser Tests gibt es bereits seit 2004. Ins Leben gerufen wurde es von Jason Huggins, während seiner Zeit bei ThoughtWorks, die zu diesem Zeitpunkt hauptsächlich mit Javascript arbeiteten. Obwohl  der InternetExplorer der beherrschende Browser war, wurden bei ThoughtWorks bereits einige alternative Browser benutzt (vor allem Mozilla Varianten). Open Source Testing Tools gab es nur für einzelne Browser (typischerweise für den InternetExplorer) oder es waren Simulationen von Browsern (z.B. HttpUnit) und die Kosten für kommerzielle Tools waren vor allem für kleine Projekte noch nicht bezahlbar .

Glücklicherweise unterstützten alle zu testenden Browser Javascript. Deshalb machten sich Jason und sein Team daran ein Testing Tool in der Sprache zu schreiben die das Verhalten ihrer Applikation am Besten verifizieren konnte. Inspiriert von dem FIT-Projekt wurde eine tabellenbasierte Syntax über das Javascript gelegt und es damit auch Nutzern mit begrenzten Programmierkenntnissen ermöglicht Tests zu schreiben. Dieses Tool wurde 2004 unter dem Namen „Selenium“ (oder auch „Selenium Core“) und unter einer Apache 2 Lizenz veröffentlicht.

Da Selenium in purem Javascript geschrieben ist, musste es auf dem gleichen Server wie die Applikation laufen, um die Browser Sicherheitsbestimmungen zu umgehen. Das war aber nicht immer möglich. Um dieses und andere Probleme zu lösen wurde ein HTTP Proxy geschrieben. Damit ließen sich viele Einschränkungen der  „Same Host Policy“ der Browser umgehen. Dieses Design ermöglichte es, Selenium-Anbindungen für viele Programmiersprachen zu schreiben. Sie mussten nur in der Lage sein eine HTTP-Anfrage an eine bestimmte URL zu schicken. Diese Version wurde bekannt als „Selenese“ oder auch „Selenium Remote Control“ (Selenium RC).

Währenddessen wurde bei ThoughtWorks an einer weiteren Browser Automatisierung gearbeitet: dem WebDriver. 2007 wurde der erste Code hierzu veröffentlicht. Er wurde für Nutzer von Projekten entwickelt, die ihre Ende-zu-Ende-Tests von dem darunterliegenden Test-Tool isolieren wollten. Typischerweise wird dies mit dem Entwurfsmuster Adapter gemacht. WebDriver entwickelte sich aus diesem Bedürfnis heraus und war ursprünglich für HTML Unit gedacht. Die Unterstützung für den InternetExplorer und Firefox folgten aber kurz nach dem Release.

Es gab erhebliche Unterschiede zwischen Selenium RC und WebDriver. Der größte Unterschied war, daß Selenium RC eine Wörterbuch-basierte API hatte, die alle Methoden für eine Klasse beanspruchte, während der WebDriver eine objektorientiertere API hatte. Außerdem unterstützte der WebDriver zunächst nur Java, während Selenium RC Unterstützung für viele Sprachen anbot. Technisch war Selenium Core hauptsächlich eine Javascript-Applikation, die in der Security-Sandbox des Browsers lief. WebDriver versuchte sich in den Browser zu integrieren, und das Browser Sicherheitsmodell zu umgehen, was einen weitaus höheren Entwicklungsaufwand zur Folge hatte.

Im August 2009 wurden beide Projekte miteinander verschmolzen. und der Selenium WebDriver ist das Resultat beider Projekte. Er unterstützt Sprachanbindungen für Java, C#, Python und Ruby. Außerdem bietet er Unterstützung für Chrome, Firefox, Internet Explorer, Opera und die Android und iPhone Browser. Es gibt Nebenprojekte die Anbindungen für Perl und eine Implementierung für den BlackBerry Browser anbieten.

Einrichten der Testumgebung 

Beispiel für Eclipse und Java

Die WebDriver API ist nicht an ein spezielles Testframework gebunden und kann sowohl in Unit Tests als auch in der guten alten Main-Methode verwendet werden.

Selenium-Server und Selenium-Client sind beide zum Download verfügbar auf folgender Seite: http://seleniumhq.org/download/

Der einfachste Weg um Selenium 2.0 mit Java zu nutzen ist es das Paket mit Maven zu integrieren. Maven lädt die java bindings (die Selenium 2.0 java client library) und alle Abhängigkeiten herunter. Dazu wird ein Projekt mit einer Maven Projektkonfigurations-Datei erstellt und der folgende Code der pom.xml hinzugefügt:

<repository>
<id>selenium</id>
<url>http://repo1.maven.org/maven2/org/seleniumhq/selenium</url> <releases> <enabled>true</enabled> <updatePolicy>daily</updatePolicy> <checksumPolicy>ignore</checksumPolicy> </releases> </repository> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId>
<version>2.23.1</version>
</dependency>

<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId<>selenium-server</artifactId>
<version>2.28.0</version>
</dependency>

Hierbei muss darauf geachtet werden, daß die letzte Version von Selenium verwendet wird! Sonst passt es nicht mit dem WebDriver zusammen.

Treiber für Browser installieren:

  • Firefox: ist der Standard-Browser für Selenium. Das heißt es muss nichts installiert werden und die Tests können sofort gestartet werden.
  • InternetExplorer: Funktioniert nur mit Windows Betriebssystemen! Um den InternetExplorer zum Testen zu benutzen muss der IE-Driver heruntergeladen und installiert werden http://code.google.com/p/selenium/downloads/list. Danach muss ein system property mit dem Namen „webdriver.ie.driver“ auf den Pfad zu dem Treiber gesetzt werden. Für IE 7 oder höher auf Windows Vista oder Windows 7, müssen die Protected Mode settings für jede Zone denselben Wert haben. Der Wert kann an oder aus sein, solange es derselbe für jede Zone ist. Um die Protected Mode settings zu setzen, wähle „Internet Options…“ in dem Tools menu des IEs, und klicke auf das Security tab. Für jede Zone gibt es eine Checkbox am unteren Ende mit der Aufschrift „Enable Protected Mode“. Das Browser zoom level muss außerdem auf 100% gesetzt werden, damit die native mouse events auf die richtigen Koordinaten gesetzt werden können. Mehr Dokumentation gibt es hier.

Wie schreibe ich einen Test?

Ich empfehle für jeden Browsertyp ein eigenes Maven-Projekt anzulegen. Das hat den Vorteil, daß die Tests für jeden Browser einzeln durchgeführt werden können, je nachdem auf welchem Rechner man sich befindet. So sind die InternetExplorer-Tests nur auf Windows-Rechnern abspielbar und es hat auch nicht jeder einen Chrome-Browser installiert.

Selenium-Tests als JUnit-Tests

Die Tests werden in diesem Beispiel als Unit-Tests angelegt. Benutzt wird JUnit4. Die Bibliothek kann ebenfalls mit Maven eingebunden werden:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>

Es wird also ein Paket für zusammengehörige Tests unter src/test/java angelegt. Später kann hier auch eine TestSuite „AllTests“ angelegt werden mit der alle Tests in dem Paket nacheinander abgespielt werden können. Dies ist aber auch mit maven-install möglich. Ein erster Testcase wird angelegt. Zugriff auf die JUnit4-Bibliothek erhält man, indem statt des voreingestellten org.junit.Assert-imports ein extends TestCase an die Testklasse geschrieben wird. Damit werden die benötigten Methoden geerbt.

Erzeugen und Zerstören des Browser-Objekts

Als erstes muss ein Browser-Treiber erzeugt werden. Je nachdem welcher Browser zum Testen benutzt werden soll, wird hier der entsprechende Treiber erzeugt. Es ist sinnvoll ein privates Attribut für den Treiber anzulegen und dann den entsprechenden Treiber in einer @Before-Methode zu erzeugen, die vor jedem Test aufgerufen wird.

private WebDriver driver;

@Before
 public void setUp() {
        driver = new FirefoxDriver();
 }
Für den Chrome-Brower muss zunächst das System property zu dem Treiber gesetzt werden:
System.setProperty("webdriver.chrome.driver", "/Applications/chromedriver");
driver = new ChromeDriver();

Für den InternetExplorer ebenso:

System.setProperty("webdriver.ie.driver",
"/DRIVERS/IEDriverServer/IEDriverServer.exe");
driver = new InternetExplorerDriver();

Ebenso ist es sinnvoll am Ende der Klasse eine @After-Methode zu haben, die den Browser wieder schließt und beendet.

@After
    public void tearDown() {
        driver.quit();
    }

Als eine weitere Arbeitserleichterung hat es sich erwiesen eine Methode zu haben, die ein bisschen Zeit verstreichen läßt zwischen den einzelnen Aktionen. Da man eine Nutzerinteraktion nachstellt, kann es immer mal wieder eine Weile dauern bis eine Seite geladen ist und bestimmte Elemente auf der Seite sichtbar sind. Dazu kann eine Methode „waitForAwhile()“ implementiert werden, die immer mal wieder während des Testens aufgerufen wird um zu Warten. Bei dem InternetExplorer muss hier mehr Zeit angegeben werden als bei Firefox und Chrome, da er für alles etwas länger braucht.

private void waitForAwhile() {
        try {
            Thread.sleep(5 * 1000);
        } catch (InterruptedException ex) {
            System.out.println("Timeout after waiting 5 seconds.");
        }
}

Danach kann die eigentliche Testmethode geschrieben werden.

Zunächst wird dem Browser-Treiber eine URL für eine Webseite mitgegeben, die getestet werden soll und direkt im Anschluss sollte die Wartemethode aufgerufen werden, da es eine Weile dauert bis der Browser gestartet und die Seite aufgerufen ist.

driver.get("http://seleniumhq.org");

waitForAwhile();

Auswahl von Elementen auf der Webseite

Jetzt können verschiedene Elemente der Seite angesteuert und bedient oder überprüft werden. Für die Auswahl der Elemente auf der Seite gibt es mehrere Möglichkeiten: nach ID, Name, Linktext, Klassenname, per CSS-Selektor oder xpath. Es kann ein einzelnes oder eine Liste von Elementen geholt werden mit findElement() oder findElements().

  • WebElement element = driver.findElement(By.id("eindeutige_id"));
  • WebElement element = driver.findElement(By.name("name"));
  • WebElement element = driver.findElement(By.tagName("tagname"));
  • WebElement element = driver.findElement(By.className("classname"));
  • WebElement element = driver.findElement(By.linkText("linktext"));
  • WebElement element = driver.findElement(By.partialLinkText("part of link"));
  • WebElement element = driver.findElement(By.cssSelector("div#id");
  • List<WebElement> inputs = driver.findElements(By.xpath("//input"));

CSS-Selektoren

Da ich sehr lange gebraucht habe, um die richtigen CSS-Selektoren anzugeben, hier ein kurzer Hinweis:

Der Pfad zu einem CSS-Element baut sich so auf, daß zunächst ein Element mit einer eindeutigen ID herangezogen wird und dann die Unterelemente, die keine ID haben über die Klassennamen angesprochen werden. Dies sieht wie folgt aus:

driver.findElement(By.cssSelector("div#id >div.classname >div.classname input.classname");
  • Hierarchie mit direct child: div#id >div.classname
  • wenn nur ein Leerzeichen dazwischen ist, nimmt es ein child oder subchild: div#id div.classname

Man kann auch ein Unterelement einer Liste von Elementen nur durch Nummerierung ansprechen, ohne den Klassennamen, mit

  • div:nth-of-type(3) oder
  • li:nth-child(2)

Aber woher weiß ich wie die Elemente heißen?

Wenn die Webseite nicht selbst programmiert wurde, kann man das natürlich nicht wissen. Die einfachste Methode das herauszufinden ist den Firebug zu benutzen und die Seite zu untersuchen.

Welche Methoden auf den Elementen ausführbar sind, läßt sich in der Selenium-Java-Api nachlesen oder einfach in Eclipse den Punkt nach dem WebElement eingeben  und schauen was einem an Methoden so angeboten wird.

Komplettes Beispiel für einen Selenium-Test zum selbst ausprobieren

Einfach ein Maven-Projekt anlegen wie oben erklärt, und den Test als JUnit-Test unter src/test/java einfügen. Dann mit RUN AS -> JUnit Test ausführen.

Downloads:

Selenium_Example.docx

Selenium_Example.pdf

Wie das Ganze dann aussieht, zeigt dieses Video:

http://www.youtube.com/watch?v=_lFcwZOnp2s?rel=0

2 commentaires sur “Automatisiertes Testen von Webseiten mit dem Selenium WebDriver

  1. Very soon this web site will be famous amid all
    blog visitors, due to it’s fastidious posts

Die Kommentarfunktion ist geschlossen.