Bei der Suche nach Python-Modulen für die automatisierte Interaktion mit Webseiten bzw. deren automatisierter Tests ist Selenium in vielen Fällen der erste Treffer. Selenium ist ein portables Test-Framework für Web-Applikationen und dessen Python-API bietet Zugriff auf die Funktionalitäten des Selenium WebDriver. Über den Treiber können verschiedene Web-Browser angesprochen und die Interaktion durch einen Benutzer simuliert werden. Doch Selenium ist bedingt durch seinen großen Funktionsumfang komplex. Eine Alternative bzw. einen einfacheren Zugang zu Selenium bietet Splinter. Was Splinter ist, welche Features es hat und wie es eingesetzt werden kann, wird in diesem Artikel erläutert.
Was ist Splinter?
Splinter ist eine Python-Bibliothek und bietet eine Abstraktionsschicht, die auf den Funktionen von Selenium, zope.testbrowser, Django Client und Flask Client zurückgreift. Die von Splinter bereitgestellte API ist leichter zugänglich, benötigt weniger Code und ist für die verschiedenen Backends identisch. Dabei unterstützt Splinter unter anderem die folgenden Features:
- CSS und XPath-Selektoren
- iFrames
- Warnhinweise von Browsern
- Ausführung von JavaScript
- Nutzung von AJAX und asynchronem JavaScript
Abhängigkeiten und Installation
Die Abhängigkeiten von Splinter und damit dessen Installation hängt von dem genutzten Backend ab. Der Fokus dieses Artikels liegt auf dem Backend Selenium, da es am flexibelsten einsetzbar ist. Die Backends Django und Flask dienen dem Testen von Applikationen, die mit dem jeweiligen Framework entwickelt wurden und der zope.testbrowser ist nur zu Python 2 kompatibel.
Für Splinter selbst ist mindestens Python in Version 2.7 erforderlich. Splinter und Selenium lassen sich am einfachsten über pip installieren. Dabei ist Selenium eine Abhängigkeit von Splinter und wird somit automatisch mit installiert.
# pip install splinter
Selenium erfordert, dass der für die Tests genutzte Browser und der entsprechende Treiber installiert sind. Das Installationsverfahren hängt vom genutzten Betriebssystem und dem Browser ab. Eine detaillierte Beschreibung für jede Kombination ist an dieser Stelle nicht sinnvoll, kann aber im Selenium Wiki (https://github.com/SeleniumHQ/selenium/wiki) nachvollzogen werden.
Schritt für Schritt in Richtung Automatisierung
Die Entwicklung von Test für Webseiten bzw. allgemeiner die automatisierte Interaktion mit Webseiten ist in der Regel ein iterativer Prozess. Möchte man z. B. die Suche auf dem Seminar-Portal der ORDIX AG automatisiert testen, müssen die einzelnen Schritte, die ein Kunde durchführt, nachvollzogen und ein Zielzustand definiert werden. In diesem Fall sucht der Kunde nach Seminaren zum Thema Python, klickt den ersten Treffer an und findet dort die Seminar-ID „P-PYTH-01". Im Folgenden werden die einzelnen Schritte aufgeführt und der entsprechende Python-Code beschrieben.
- Chrome Browser öffnen und die Webseite https://seminare.ordix.de/ aufrufen
Das Splinter-Browser-Objekt nutzt standardmäßig Firefox. Soll ein anderer Browser genutzt werden, muss dieser beim Erstellen des Objektes angegeben werden. Mit der Methode visit() wird die entsprechende Webseite aufgerufen.
>>> from splinter import Browser
>>> b = Browser('chrome')
>>> b.visit('https://seminare.ordix.de') - Nach Schulungen zum Thema Python suchen
Für die Automatisierung dieses Tasks muss Splinter die zu verwendenden Elemente der Webseite kennen. Um die Elemente zu identifizieren, können beim Chrome die DevTools (öffnen sich mit F12) genutzt werden. Über die Tastenkombination Strg+Shift+C wird der „Inspector" geöffnet, der ermöglicht, das zu untersuchende Element auszuwählen (siehe Abbildung 1). Splinter kann die entsprechenden Elemente, in diesem Fall die Searchbox und den Button „Suchen", anhand verschiedener Eigenschaften (CSS, XPath, Tag, Name, ID, Value und Text) identifizieren. Für jede dieser Eigenschaften bietet das Browser-Objekt eine entsprechende find_by_<property>()-Methode. Diese geben eine Liste mit den gefundenen WebDriverElement-Objekten zurück. Je nach Typ des Elementes sind unterschiedliche Interaktionen sinnvoll (z. B. Füllen eines Formulars oder Klicken eines Buttons). Wird eine Methode auf die Liste angewandt, ist die Liste ein Stellvertreter für das erste Element.
>>> s_box = b.find_by_id('searchBox')
>>> s_box
[<splinter.driver.webdriver.WebDriverElement object at 0x0000028EAC352E80>]
# die folgenden drei Zeilen fügen in das erste Element mit der ID „searchBox" den String „Python" ein
>>> s_box[0].fill('Python')
>>> s_box.first.fill('Python')
>>> s_box.fill('Python')
>>> b.find_by_id('ss360SearchButton').click() - Den ersten Treffer anklicken, die ID überprüfen und den Browser schließen
Für das Auffinden der entsprechenden Elemente können die unterschiedlichen Eigenschaften genutzt werden. Die ID des Seminars steht in dem letzten Element mit dem Tag h1, dessen Wert über das Attribut value abrufbar ist.
>>> b.find_by_css('a[class="ss360-result-link"]').click()
>>> h1 = b.find_by_tag('h1')
>>> h1.last.value == 'P-PYTH-01'
True
>>> b.quit()
Die im Beispiel vorgestellten Methoden zum Auffinden von Elementen sowie die Möglichkeiten mit den verschiedenen Elementen zu interagieren ermöglichen schon die Erstellung von komplexen Tests. Im folgenden Abschnitt werden weitere Funktionen von Splinter vorgestellt, um einen möglichst umfangreichen Überblick zu geben.
Was geht sonst noch?
Für automatisierte Tasks ist es selten notwendig, dass ein tatsächliches Fenster geöffnet wird. Daher können die Tests auch „headless" durchgeführt werden.
>>> Browser('chrome', headless=True)
Darüber hinaus können abhängig vom genutzten Browser verschiedene Features des Browsers wie z. B. der Inkognitomodus oder die Emulation von mobilen Devices verwendet werden. In diesen Zusammenhang passt auch die Möglichkeit verschiedene Fenster zu verwalten, wenn z. B. die Webseite ein Popup öffnet.
Mit Splinter lassen sich Interaktionen mit der Maus simulieren. Dies beinhaltet Mouse-Over-Events, Klicks mit verschiedenen Maustasten oder Drag-and-Drop-Aktionen. Zudem können Screenshots des gesamten Fensters oder nur von einem Element erstellt und in einer PNG-Datei gespeichert werden. Dazu kann die Methode screenshot() entweder auf das Browser-Objekt oder auf ein spezifisches Element angewendet werden.
Und da geht noch mehr… Das Handling von Fehlern und Hinweismeldungen, die Manipulation von Cookies, das Ausführen von JavaScript, sowie die Unterstützung von AJAX und asynchronem JavaScript lassen sich in ähnlicher Weise implementieren.
Fazit
Die Titelfrage „Muss es Selenium sein oder reicht Splinter?" lässt sich mit einem klaren „Jein" beantworten. Wie das Beispiel zeigt, reicht in vielen Fällen Splinter aus und bietet eine einfache Möglichkeit die Interaktion mit Webseiten zu automatisieren. Da Splinter im Vergleich zu Selenium leichter anzuwenden ist, ist es sinnvoll, Splinter zu verwenden, wenn es die benötigten Features bereitstellt. Dies gilt insbesondere, wenn man noch keine Erfahrung mit Selenium für Python hat. Werden jedoch Features außerhalb des Scopes von Splinter benötigt, ist tatsächlich Selenium die erste Wahl.