Kurs:Neueste Internet- und WWW-Technologien/Web-Tests mit Selenium

Was ist Selenium

Bearbeiten

Selenium ist ein Framework für Browserautomatisierung und Testframework für Webapplikationen. Es führt reale Interaktionen mit Webseiten durch. So kann Selenium z.B. automatisch einen Browser öffnen, zu einer URL navigieren, Text eingeben, einen Button anklicken danach testen ob die Fehlermeldung im resultierenden Popup auf der Seite die richtige ist. Damit kann viel normalerweise manuelles, zeitaufwändiges Testen (z.B. das Ausfüllen von Formularen) automatisiert werden. Selenium läuft auf vielen Plattformen inkl. Windows, Linux und Mac.[1]

Vorteile von Selenium

Bearbeiten

In den häufig eingesetzten Testingframeworks moderner Programmiersprachen, wie JUnit, RSpec etc. werden hauptsächlich Module oder Funktionen getestet. Dieser Ansatz funktioniert auch mit Webapps recht gut, so können z.B. die Controllerfunktionen (in einer Model-View-Controller Architektur) einer Webanwendung getestet werden. Auch die Interaktion per HTTP (GET, POST Requests) kann mit speziellen Bibliotheken recht bequem getestet werden. Bei interaktiven, mit viel Javascript und Ajax geschriebenen Seiten versagt dieser Ansatz. Das Javascript wird ausgeführt und interagiert mit dem Document Object Model (DOM) der Webseite. Dies ist mit den traditionellen Testingframeworks nicht testbar, da das Ausführen von Javascript nicht unterstützt wird. Dies ist verständlich, da sie hauptsächlich für das Testen der Entwicklungssprache gedacht sind. Statt nun Frameworks mit einem Javascriptinterpreter auszurüsten kann mit Selenium der Browser und deren - bereits bestehende und im Alltag verwendete - HTML-Renderer und Javascript-Engines verwendet werden.

Entwicklung / Geschichte

Bearbeiten

Selenium wurde ursprünglich 2004 von der amerikanischen Firma ThoughtWorks entwickelt. Das Projekt ist freie Software und steht unter der Apache 2.0 Lizenz[2]. Das Projekt wird von der Community weiterentwickelt, wobei auch Mitarbeiter von Google zum Projekt beitragen[3]. Mehrere kommerzielle Firmen bieten Support für den professionellen Einsatz an[4].

Selenium im Einsatz

Bearbeiten
Datei:Selenium ide2.png
Die Selenium IDE

Selenium kann in zwei verschiedenen Varianten eingesetzt werden:

  • Selenium IDE, ein Firefox Add-on das Browserinteraktionen aufzeichnen und wiedergeben kann. Mit Selenium IDE können Tests auch ohne Kenntnisse einer Programmiersprache erstellt werden können. Weiterhin gibt es die Möglichkeit Tests zu bearbeitet und diese zu exportieren.
  • Selenium WebDriver, eine Sammlung von Selenium-Bindings für die gängisten Programmiersprachen, mit denen Seleniumtests in der Sprache der Wahl geschrieben werden können.

Selenium IDE

Bearbeiten
Datei:Selenium IDE short.ogv
Kurze Demonstration der Selenium IDE.

Die Selenium IDE ist ein Werkzeug um protototypisch Testskripte zu erstellen. IDE soll in diesem Zusammenhang für Integrated Development Environment stehen, d.h. es wird eine komplette integrierte Entwicklungsumgebung für Seleniumtests als Plugin für Firefox zur Verfügung gestellt. Unter anderem bietet die IDE Auswahl von HTML-Elementen per ID, name oder XPath, Autovervollständigung und Debugging per Haltepunkten[5], sowie viele weitere Funktionalität (z.B. einen Screenshot bei Fehlern zu erstellen[6]) durch den Einsatz von Plugins[7]. Die so erstellten Tests können als wiederverwendbares Skript (in verschiedenen Programmiersprachen) exportiert werden. Die Selenium IDE bietet jedoch nicht den gesamten Funktionsumfang des Selenium-Frameworks. So sind Iterationen oder bedingte Anweisungen nicht vorgesehen und die IDE soll nicht verwendet werden um grosse Testsuiten auszuführen. Für größere, komplexere Tests wird WebDriver empfohlen.

Download / Dokumentation

Bearbeiten

Die Selenium IDE .xpi (Firefox add-on) muss direkt von der Selenium Downloadeite heruntergeladen werden, da sie nicht auf der offiziellen Mozilla Add-ons Webseite verfügbar ist. Viele Plugins für die IDE befinden sich jedoch auf der Add-on Seite. Es gibt eine ausführliche Dokumentation zur Selenium IDE, die Installation und Verwendung genau erläutert.

Einfaches Beispiel

Bearbeiten

Selenium WebDriver

Bearbeiten

Der WebDriver stellt eine objektorientierte API zum Browser dar. WebDriver schickt Befehle direkt an den Browser über dessen eingebaute Automatisierungsschnittstellen. Für jede Programmiersprache kommen verschiedene Bindings zum Einsatz. Folgende Sprachen werden vom Hauptprojekt unterstützt[7] und verwenden Firefox:

  • Java
  • C#
  • Ruby
  • Python

Auch für mobile Plattformen (Android[8] und iOS[9]) gibt es WebDriver. Weitere Browserunterstützung (z.b. für Chrome, Opera) und WebDriver (z.B. für PHP oder Perl)[7] werden von der Community entwickelt und gepflegt.

Download / Dokumentation

Bearbeiten

Um WebDriver einzusetzen, gilt es sich für eine Programmiersprache zu entscheiden, für die Selenium Bindings existieren und mit der die Tests geschrieben werden sollen. Als Programmiersprache soll hier Python eingesetzt werden. Dazu muss der richige WebDriver installiert werden, Da sich dieser im Python Package Index befindet kann er mit dem Kommandozeilenaufruf pip install selenium (benötigt PIP) installiert werden. Die Dokumentation hält auch Schritte zu Installation für WebDriver für andere Programmiersprachen bereit.

Einfaches Beispiel

Bearbeiten

Auch in diesem Beispiel soll wieder mit einer Suchmaschine gesucht und die Ergebnisse getestet werden.

Nachdem der WebDriver importiert wurde, steht ein Objekt bereit, welches den Webbrowser darstellt und an das Kommandos gesendet werden können. Damit könnten nun Automatisierungsskripte realisiert werden. Um einen Test umzusetzen sollte ein Testframework zum Einsatz kommen. Hier wird das de facto Standard Python-Testframework unittest verwendet. Mit dessen Hilfe ist es möglich (programmatisch) einen Test zu definieren, der den Webbrowser automatisiert. Firefox wird automatisch geöffnet und vollzieht die Schritte.

#encoding: utf-8
from selenium import webdriver
import unittest

class TestBing(unittest.TestCase):
    # Wird vor dem Test ausgeführt
    def setUp(self):
        # Verwende Firefox
        self.driver = webdriver.Firefox()
        # Setze timeout für alle weiteren Kommandos
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.bing.com"
    
    # Methode, die den eigentlichen Test durchführt
    def test_bing(self):
        driver = self.driver
        # Hole die Webseite
        driver.get(self.base_url + "/?cc=de")
        # Prüfe, ob der Titel stimmt
        self.assertEqual("Bing", driver.title)

        # Suche das Eingabefeld...
        input = driver.find_element_by_id("sb_form_q")
        input.click()
        input.clear()
        # ...und schreibe "Selenium" hinein
        input.send_keys("selenium")

        # Schicke das Formular ab
        search_button = driver.find_element_by_id("sb_form_go")
        search_button.click()

        # Überprüfe den Titel der Seite
        self.assertEqual("selenium - Bing", driver.title)

    # Wird nach dem Test ausgeführt. Aufräumen.
    def tearDown(self):
        self.driver.quit()

# Der Test kann mit python <dateiname>.py gerufen werden
if __name__ == "__main__":
    unittest.main()

Im obigen Beispiel wird mit der Suchmaschine Bing (der Fairness wegen) nach "Selenium" gesucht und überprüft, ob der Titel der resultierenden Webseite stimmt. Es konnten die bewährten Strukturen eines Testcase verwendet werden. Dies ist derselbe Funktionsumfang, der auch mit der Selenium IDE einfach zu erreichen ist.

Erweiterte Möglichkeiten

Bearbeiten

Indem Tests mit einer Programmiersprache geschrieben werden können, stehen mehr Möglichkeiten zur Verfügung. So können alle Konstrukte der Programmiersprache verwendet werden.

#encoding: utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
import unittest, re

class TestBing(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.bing.com"
    
    def test_bing(self):
        driver = self.driver
        driver.get(self.base_url + "/?cc=de")
        self.assertEqual("Bing", driver.title)
        input = driver.find_element_by_id("sb_form_q")
        input.click()
        input.clear()
        input.send_keys("selenium")
        search_button = driver.find_element_by_id("sb_form_go")
        search_button.click()
        self.assertEqual("selenium - Bing", driver.title)

        # Prüfe, ob ein Link mit dem Text "Selenium - Web Browser Automation" existiert.
        self.assertTrue(self.is_element_present(By.LINK_TEXT, "Selenium - Web Browser Automation"))
        # Verwende einen regulären Ausdruck, um zu prüfen, ob "Wikipedia" in den Suchergebnissen auftaucht.
        self.assertRegexpMatches(driver.find_element_by_css_selector("div.sb_tlst > h3 > a").text, r"^[\s\S]*Wikipedia$")
        # Folge dem "Selenium – Wikipedia" Link.
        driver.find_element_by_link_text("Selenium – Wikipedia").click()

        for x in range(3):
            # Folge dem "Selenium – Wikipedia" Link.
            driver.find_element_by_link_text("Selenium – Wikipedia").click()

            # Verwende den "Zurück"-Button des Browsers um zur vorherigen Seite zu kommen.
            driver.back()
            # Prüfe, ob das Zurücknavigieren erfolgreich war.
            self.assertEqual("selenium - Bing", driver.title)

        # Überprüfe, dass ein Cookie von Bing gesetzt wurde.
        cookies = driver.get_cookies()
        self.assertTrue(len(cookies) != 0)
        cookie_domains = [cookie['domain'] for cookie in cookies]        
        self.assertTrue('www.bing.com' in cookie_domains)
        # Gebe alle gesetzten Cookies aus.
        for cookie in cookies:
                print "%s: %s -> %s" % (cookie['domain'], cookie['name'], cookie['value'])
    
    # Hilfsfunktion, die überprüft, ob ein Element vorhanden ist.
    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except NoSuchElementException, e: return False
        return True
    
    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main()
Datei:Selenium test.ogv
Der obige Selenium-Test in Ausführung. Der Firefox wird vollständig automatisiert. Es findet keine Interakttion mit der Maus statt.

Das obige Beispiel erweitert den Code (die kommentierten Zeilen sind hinzugekommen) des einfachen Beispiels um die Prüfung des Inhalts per regulärem Ausdruck, die Verwendung des "Zurück"-Buttons und Konstrollkonstrukte der Programmiersprache. Damit steigt die Ausdruckskraft von Tests erheblich. Alle Kommandos, die an den Webbrowser gesendet werden können, zusammen mit ausführlichen Informationen finden sich in der Dokumentation.

Selenium für Akzeptanztests

Bearbeiten
Datei:Cucumber test.png
Ein natürlichsprachlicher Cucumber-Test[10].


Datei:Cucumber steps.png
Die Implementierung der Cucumber Schritte (geschrieben in Ruby)[11].

Mit Selenium lassen sich sehr gut die beobachtbaren Eigenschaften einer Webanwendung testen. Dies ist von großem Nutzen wenn es um Akzeptanztests für Anforderungenn geht. In einem agilen Softwareentwicklungsprozess in dem verhaltensgetriebene oder testgetriebene Entwicklungsstrategien eingesetzt werden, kann Selenium besonders gut eingesetzt werden. In diesen Modellen werden Anforderungen und Ziele textuell festgehalten, um sie später automatisiert auf ihre korrekte Implementierung testen zu können. In diesem Zusammenhang kann Selenium in Kombination mit einem weiteren Testframework, welches die Darstellung von Tests in natürlicher Sprache erlaubt, eingesetzt werden. Ein solches Framework ist z.B. Cucumber. Mit dessen Hilfe können nun (eventuell sogar durch Beteiligte, die nicht Softwareentwickler sind) Tests in natürlicher Sprache geschrieben werden. Der Vorteil von Selenium als Backend liegt hier darin, dass die Anwendung als Black-Box getestet wird, d.h. es wird nicht der Code direkt, sondern nur das Verhalten des Software bei Benutzung mit einem Browser geprüft und es ist möglich Javascript und die Oberfläche zu testen.

Selenium Grid

Bearbeiten

Um sehr große, komplexe Tests ausführen zu können und um Tests auf verschiedenen Plattformen ausführen zu können, wurde Selenium Grid entwickelt. Grid erlaubt es, Tests parallel auf verschieden Computer auszuführen. Zum einen kann somit die benötigte Zeit für einen Testdurchlauf verringert werden, auf der anderen Seite aber der gleiche Test auf verschiedenen Plattformen mit verschiedensten Browsern gleichzeitig ausgeführt werden. Grid kommt zum Beispiell bei eBay zum Einsatz, deren Entwickler auch zum Projekt beitragen[12].

Selenium Dokumentation, Selenium Project, http://seleniumhq.org/docs/, abgerufen am 22.07.12.

Einzelnachweise

Bearbeiten
  1. Durch Selenium unterstützte Betriebssysteme, abgerufen am 13.05.2012.
  2. Selenium Lizenz, abgerufen am 13.05.2012.
  3. Mitwirkende von Selenium, abgerufen am 13.05.2012.
  4. Kommerzielle Firmen die Selenium-Support anbieten, abgerufen am 17.05.2012.
  5. Selenium IDE Features, abgerufen am 17.05.2012.
  6. "Screenshot on Fail" v1.0 Selenium Plugin, abgerufen am 17.05.2012.
  7. 7,0 7,1 7,2 Selenium IDE Plugins Download, abgerufen am 17.05.2012.
  8. AndroidDriver, WebDriver für Android.
  9. IPhoneDriver, WebDriver für iOS.
  10. Cucumber Additions-Test, abgerufen am 22.07.12.
  11. Implementierung der Cucumber-Schritte, abgerufen am 22.07.12.
  12. Selenium Mailingliste, abgerufen am 22.07.12.