Dieses Selenium Tutorial soll Grundlagen in der Testautomatisierung mit Selenium am Beispiel unserer Testing-Board WordPress Website vermitteln. Dazu brauchen wir automatisierte Testskripte in Selenium und ein paar Testing-Tools drum herum. Wir nutzen Selenium Webdriver, dies wird auch Selenium 2 genannt.
Endziel: Ein Hybrides Selenium Testframework, Data-Driven und Keyword-driven
Neben den Grundlagen wollen wir nach und nach vermitteln, wie wir ein Selenium–Testframework generieren und den Code so strukturieren, dass jemand ohne ausgiebige Programmierkenntnisse Testfälle erstellen kann. Zunächst bleiben wir damit nur innerhalb der Java-Programmierung bzw. in Selenium und zeigen dort ein paar Beispiele. Später ergänzen wir dies um Excel und TestNG, um so ein echtes Hybrides, Data-Driven (Datengetriebener Test) und Keyword-Driven (Schüsselwortbasierter Test) Testframework zu bekommen.
Vorbereitungen:
- Aktuelles Java installieren
- Aktuellen Firefox installieren
- Addon Firebug in Firefox installieren
- Aktuelles Chrome installieren
Selenium Download und Installation:
Wir starten mit dem Download und Selenium Installation. Der Selenium Download befindet sich hier: Link.
Dort sehen wir diverse Selenium-Versionen, die verschiedene Programmiersprachen unterstützen, in welchen die Testscripte geschrieben werden. Wir entscheiden uns für Java. Java bietet eine Plattformunabhängigkeit und wird dato in den meisten Softwareentwicklungsprojekten verwendet.
Nun den Download tätigen und das Zip an einem beliebigen Ort entpacken.
Nicht erschrecken vor OpenSource – Selenium in Eclipse
Wer nun Testautomatisierungs-Tools wie HP UFT (früher HP QTP) oder Micro Focus Silk Test gewohnt ist, wird sich wundern, dass keine Executable (*.exe) oder ein Installationsfile vorhanden ist und man ebenfalls nicht von Anfang an mit Tool-gestützter-Online-Anleitung im Testautomatisierungstool an die Hand genommen und geführt wird. Diesen Komfort haben wir in OpenSource Tools oft nicht, was Selenium aber nicht zu einem schlechten Testautomatisierungs-Werkzeug macht. Im Gegenteil, Selenium wird vom Kleinunternehmen bis zu Konzernen sehr oft verwendet und gilt neben den kommerziellen, teuren Test-Automation-Tools als ein Standard-Testing-Tool.
Es gibt auch eine Selenium-GUI bzw. Selenium-IDE für Firefox. Dies soll aber nicht Teil dieses Selenium Tutorials sein. Besonders für größere Software- bzw. Testing-Projekt spielt diese Selenium IDE eher eine untergeordnete Rolle.
Blicken wir in das eben runtergeladene Selenium-Zip, sehen wir anstatt einer Executable ein paar JAR-Dateien. Diese wollen nun in eine Entwicklungsumgebung eingebunden werden.
Selenium in Eclipse IDE und das Projekt einrichten
Wir nutzen Selenium, wie in Testautomatisierungs-Projekten auch üblich, direkt in einer Entwicklungsumgebung bzw. Entwicklungs-IDE. Wir entscheiden uns für Eclipse. Somit muss Eclipse installiert sein, was nicht Teil des Tutorials ist, aber keine Hürde darstellen sollte. Wir verwenden die Eclipse Version „Eclipse IDE for Java Developers 64 Bit“. Eclipse Download hier: Link.
Falls beim Eclipse-Start eine Fehlermeldung kommt, könnte es daran liegen, dass die Java Version aktualisiert werden sollte. Java Download Windows: Link.
Beim Eclipse Start wählen wir einen Workspace, welcher angibt, wo wir Eclipse Projekte speichern möchten.
In Eclipse legen wir nun ein neues „Java Project“ an („File“ → „New“ → „Java Project“), in unserem Fall nennen wir es „Selenium-Testing-Board“. Beim Anlegen des Projekts können wir fast alle Einstellung auf Default-Werte belassen, aber wir fügen die JAR-Files aus dem entpackten Selenium-Zip-Ordner direkt als Libraries unter dem Reiter „Libraries“ hinzu.
Über den Button „Add External JARs…“ fügen wir alle Selenium JARs hinzu.
Und wir fügen auch direkt alle Selenium JARs aus dem „libs“-Unterordner im entpackten Selenium Ordner hinzu. Der „libs“-Ordner ist oben auch im Screenshot zu sehen und enthält viele weitere JARs.
Haben wir bei der Anlage des neuen Java-Projekts alle Selenium JARs ausgewählt, sollte es wie folgt aussehen.
Mit „Finish“ bestätigen wir das Erstellen des Java-Projekts.
In bereits bestehenden Projekten in Eclipse können die JARs selbstverständlich auch hinzugefügt werden. Falls wir vergessen beim Anlegen des Java-Projekts die Selenium Libraries von Selenium in unserem Eclipse Java-Projekt zuzufügen oder dies in einem vorhandenen Projekt tun möchten, können wir es auch nachträglich. Dazu einfach ein Rechts-Klick in Eclipse auf das Projekt und unter „Properties“ im Menü „Java Build Path“ und Reiter „Libraries“ können auch alle JARs mit „Add External JARs…“ zugefügt werden. Dies sieht wie folgt aus.
Für den Rest des Tutorials wird ein wenig Eclipse Knowhow vorausgesetzt. Fragen gerne in den Kommentaren.
Java in Eclipse: Hello Testing-Board readers
Wir navigieren uns in Eclipse im „Package Explorer“ in die Source Dateien, diese sind durch „src“ dargestellt. In den Library Ordnern sehen wir beim Aufklappen auch unsere eben hinzugefügten JARs. Letztere sind uns aber nun erst einmal egal.
Wir legen nun eine erste Java-Klasse bzw. *.java Datei in einem Java-Package an. In unserem Fall mit dem Titel „tbCom_Hello“. Dazu unter „src“ eine neue „Class“ mit dem jeweiligen Titel als Name erstellen.
Package belassen wir als Default.
Nun sollte unser Eclipse Selenium Projekt wie folgt aussehen:
Unser erster Code hat mit Testautomatisierung in Selenium noch nicht viel zu tun, aber alles Schritt für Schritt. Unser erster Code: Eine typische Art “Hello Word”
tbCom_Hello.java
public class tbCom_Hello { public static void main(String[] args) { String string_hello = "Hello Testing-Board Reader!"; System.out.println(string_hello); } }
Nun drücken wir oben den grünen Play-Knopf und lassen das Script laufen. Unten in der Console sehen wir dann unseren Text-String. Dies war ein kurzes „Hello World“, um uns nochmal Java und die Ausführung von Java in Eclipse näher zu bringen.
Start der Testautomatisierung in Selenium – Firefox
Im Anhang und Quellenverzeichnis ist ein YouTube Video verlinkt, dass zusätzlich noch etwas die Objektorientierte Programmierung erklärt. In diesem Tutorial erläutern wir die folgenden Code-Beispiele nicht direkt.
Alle Java Selenium Funktionen sind in der Selenium Java API beschrieben. Link dazu hier: Java API
Da wir die Selenium JARs in unser Eclipse Projekt importiert haben, haben wir alle Klassen und damit alle Funktionen, die uns Selenium liefert. Wir müssen diese Selenium-Funktionen nun in einfachen Skripten ausführen, in unserem automatisierten Testfall bzw. Testszenario.
Dazu legen wir wieder unter „src“ in Eclipse in unserem Default Package eine neue Klasse (new Class) an. Titel “start_firefox“.
Um den Firefox Browser mit Selenium anzusprechen brauchen wir die nötigen Selenium Funktionen dazu, diese importieren wir in unsere Klasse aus „org.openqa.selenium.firefox.FirefoxDriver“. Mit Selenium können wir auch Chrome oder den IE (Internet Explorer) steuern und genau dies wird über die Wahl des *Drivers gesteuert. Wir starten in diesem Fall mit dem Firefox.
Unser erster Versuch soll zunächst nur ein Objekt vom Selenium Webdriver FirefoxDriver erzeugen. Wenn wir folgende Programmzeilen starten, wird dies bereits eine Firefox Instanz starten. Um Selenium Webdriver Funktionalitäten zu nutzen, müssen wir stets Packages bzw. Klassen importieren. Zu sehen in der ersten Zeile als „org.openqa.selenium.firefox.FirefoxDriver“. Eclipse meckert fehlende Klassen an und unterstützt auch dabei die fehlende Klasse durch einfache Klicks zu importieren.
start_firefox.java
import org.openqa.selenium.firefox.FirefoxDriver; public class start_firefox { public static void main(String[] args) { new FirefoxDriver(); } }
Ein Klick auf den grünen Play-Button (fortan sprechen wir nur noch von „Ausführung“) wird eine leere Firefox Instanz öffnen. Haben wir bereits einen Firefox geöffnet, wird eine neue Firefox Instanz eröffnet. Nun haben wir unsere Basis, um uns mit automatisierten Tests im Web zu bewegen. Als nächstes führen wir automatisiert Aktionen im Firefox aus.
Automatisierter Aufruf der Startseite über Selenium im Firefox
In folgendem Beispiel schicken wir direkt zwei virtuelle Tester im Firefox auf dem Weg. Und rufen in beiden Firefox Instanzen unsere Webseite auf. Wir verwenden dazu zwei Objekte, wie zuvor gesehen und vergeben beiden einen Name. Sie können dazu eine neue Java-Class Datei anlegen oder in der alten bleiben, wie es Ihnen beliebt. Legen Sie fortan für das Tutorial pro Veränderung gerne neue Java-Class-Dateien an, um die alten Schritte weiter einzusehen oder verändern Sie einfach den Datei-Inhalt einer vorhandenen Java Datei. An der „Class“ im nächsten Fall „start_2firefox_goto_homepage“, sieht man immer welchen Dateinamen wir verwendet haben.
fox1 und fox2 sind sozusagen unsere beiden virtuellen Tester, unterwegs mit dem Firefox um Testszenarien auszuführen.
start_2firefox_goto_homepage.java
import org.openqa.selenium.firefox.FirefoxDriver; public class start_2firefox_goto_homepage { public static void main(String[] args) { FirefoxDriver fox1 = new FirefoxDriver(); FirefoxDriver fox2 = new FirefoxDriver(); fox1.get("https://www.testing-board.com"); fox2.get("https://www.testing-board.com"); } }
Exkurs: Selenium und Webserver Authentication/ HTTP-Authentifizierung / Basic Authentication
Nun wollen wir gegebenenfalls nicht mit unseren virtuellen Selenium Usern die echte, produktive Webseite verwüsten, sondern eine Testinstanz. Wer nun den Link https://www.testinst.testing-board.com ausprobiert, wird feststellen, dass wir hier sogar eine WordPress-Testinstanz haben, die hinter einer HTTP-Authentifizierung sitzt. Nun können wir unseren Testfällen beibringen, an diesem Basic Auth vorbei zu kommen.
Dafür gibt es verschiedene Möglichkeiten in verschiedenen Browsern. Wir begnügen uns mit dem einfachen Weg, die Credentials direkt beim Aufrufen der Webseite zu übergeben.
Dazu legen wir eine neue Methode mit Name „get_TBcom_with_basic_auth“ an. Mit folgendem Inhalt.
public static void get_TBcom_with_basic_auth(FirefoxDriver foxDr) { String URL = "http://" + "UsernameHTTPAuth" + ":" + "PasswortHTTPAuth" + "@" + "www.testinst.testing-board.com"; foxDr.get(URL); }
Rufen wir dieses mit einem Firefox Driver auf, kommen wir problemlos auf die Webseite. Unser eben neu angelegte Methode müssen wir in der „Main-Methode“ (public static void main(String[] args)) aufrufen. Die Main-Methode ist immer die Methode, die beim Ausführen der Java-Klasse gestartet wird. Man beachte, dass wir in folgendem Beispiel die Webseite www.testinst.testing-board.com aufrufen, auf welche wir ohne Basic-Auth Credentials nicht drauf kommen. Insgesamt sieht unser Skript dann wie folgt aus.
test_basic_auth_website.java
import org.openqa.selenium.firefox.FirefoxDriver; public class test_basic_auth_website { public static void main(String[] args) { FirefoxDriver fox1 = new FirefoxDriver(); get_TBcom_with_basic_auth(fox1); } public static void get_TBcom_with_basic_auth(FirefoxDriver foxDr) { String URL = "http://" + "UsernameHTTPAuth" + ":" + "PasswortHTTPAuth" + "@" + "www.testinst.testing-board.com"; foxDr.get(URL); } }
Zur Ausführung öffnet eine Firefox Instanz und lädt problemlos die Webseite hinter dem HTTP-Basic-Auth. Den zweiten Firefox Driver haben wir erst einmal wieder raus genommen, denn zur Ausführung von mehreren Browser Instanzen parallel kommt in späteren Tutorials mehr.
Allerdings haben wir noch ein Problem. Mit dieser Lösung kommen wir zwar auf die WordPress-Frontpage, da die Basic Auth Credentials direkt in der URL sind. Wenn wir das Selenium Skript laufen lassen und die Seite im Browser öffnet und wir dann manuell einen Link klicken, kommt die Basic-Auth-Abfrage aber wieder. Auf diesem Weg werden die Daten somit nicht im Browser persistiert. Dieses kann man auch leicht nachstellen, indem man diesen Weg manuell im Browser versucht.
Im Web findet man dazu endlos verschiedene Workarounds für verschiedene Browser Versionen. Hier schlägt ein wenig „OpenSource“ durch, da viele kommerzielle Produkte von sich aus einfach bedienbare Settings dafür bieten. Wobei sich da wieder die Frage stellt, ob die Lösungen der kommerziellen Anbieter dann in jedem Browser und in jeder Version funktionieren. Hier der offizielle Support Thread von Selenium zu dem Thema Basic Auth. Und hier eine aktuelle Diskussion dazu bei Github.
In dem weiteren Tutorial wird gezeigt, dass wir Skripte dynamisch mit verschiedenen Browsern ausführen. Dies ist in solchen Fällen wichtig, da zum Beispiel für dieses Basic-Auth für verschiedene Browser und Versionen andere Lösungen nötig sind. Sprich, später sollte unser Testautomatisierungsprojekt so aussehen, dass unabhängig davon, welcher Browser von unserer Testausführung bedient wird, die Methode get_TBcom_with_basic_auth intern auf den Browser prüfen sollte und die jeweilige passende Lösung dann je nach Browser wählt und anwendet.
Exkurs: Vorbereitung Testautomatisierung Google Chrome
Chrome lässt sich nicht so 100%-„out of the box“ automatisieren wie Firefox. Für den Chrome-Browser müssen wir hier eine Executable für den ChromeDriver laden. Unter dem Link müssen wir uns für eine Version entscheiden, wie wählen 2.20.
Diese Version ist auch auf der Selenium Download Page verlinkt.
Auf dieser Seite wählen wir den Selenium ChromeDriver für unser Betriebssystem aus, in unserem Fall die Datei „chromedriver_win32.zip“.
Darin ist eine „chromedriver.exe“, welche an einem beliebigen Ort zu entpacken ist. Um das Projekt in Eclipse vollständig zu haben und auch später auf verschiedenen Server ausführen zu können, fügen wir die Datei direkt dem Eclipse Projekt hinzu.
In unserem Fall erweitern wir das Java Projekt um ein Verzeichnis, indem wir im Package Explorer per Rechts-Klick auf den Projektname, über das Kontextmenü „New -> Folder“, ein neues Verzeichnis hinzufügen. Nun können wir unsere ChromeDriver Datei, in das Verzeichnis kopieren. Um die Datei genauer zu beschreiben, benennen wir sie vorher noch um und geben Versionsnummer und OS mit in den Name „chromedriver_Win_220.exe“. Danach können wir die Datei per Standard Copy&Paste aus dem Windows-Explorer direkt in Eclipse rein kopieren.
Bei uns sieht das dann wie folgt aus:
Bevor wir den Selenium ChromeDriver in Java instanziieren können, müssen wir im Code nötige System Properties zu der eben geladenen Executable anlegen, um Selenium mitzuteilen, welche Version des ChromeDrivers verwendet wird.
Man beachte in folgendem Code-Beispiel die Doppel-Slahes „//“ anstatt den in Windows üblichen Backslash „\“, was in Java nötig ist. Weiterhin verwenden wir keinen vollqualifizierten Pfad, da wir das Selenium Projekt ja ohne Anpassungen verschieben können möchten. Aus diesem Grund vergeben wird einen relativen Pfad, innerhalb unseres Eclipse Selenium Java Projekts: „.//ChromeDriver//chromedriver_Win_220.exe“
Ähnliches muss für den Internet Explorer (IE), Opera und anderen Browsern getan werden, um diese einzubinden. Wir begnügen uns für das Tutorial mit Firefox und Chrome.
In unserem Fall sieht der Code dann wie folgt aus.
testChrome.java
import org.openqa.selenium.chrome.ChromeDriver; public class testChrome { public static void main(String[] args) { String pathToChromeDriver = ".//ChromeDriver//chromedriver_Win_220.exe"; System.setProperty("webdriver.chrome.driver", pathToChromeDriver); ChromeDriver Chrom1 = new ChromeDriver(); Chrom1.get("https://www.testinst.testing-board.com/"); } }
Bei der Ausführung stoßen wir natürlich wieder auf das HTTP Basic-Auth, da wir hier nochmal auf die Webseite „https://www.testinst.testing-board.com“ gehen. Wir lassen den Basic-Auth Exkurs aber an der Stelle und gehen in unseren Code-Beispielen fortan auf die normale, produktive WordPress Webseite. Wenn Sie das Code-Beispiel oben starten und Chrome öffnet sich und zeigt die Authentifizierungs-Abfrage, lief also alles korrekt.
Mit der eingebundenen umbenannten ChromeDriver Datei eingefügt in ein neues Verzeichnis im Java-Projekt in Eclipse und dem obigen Code-Beispiel, sollte dies dann insgesamt wie folgt aussehen.
Testframework offen für Cross-browser Testing
Wir wollen unser Testframework offen für verschiedene Browser haben (Cross Browser Testing) und wir wollen zudem auf keinen Fall redundanten Code haben, nur weil wir die Test mit verschiedenem Browsern ausführen möchten. Deshalb erfassen wir eine neue Methode „init_Browser“, in welcher wir evaluieren, welcher Browser genutzt werden soll. Aktuell belassen wir es dabei, dass wir die Wahl des Browsers im ersten Beispiel als Argument beim Aufruf des Testfalls mit übergeben können.
So wird bei Aufruf der Klasse mit „Chrome“ oder „Firefox“ als Skriptparameter der jeweilige Browser verwendet. So haben wir die Möglichkeit, die Testfälle beispielsweise aus einem Testmanagement-Tool oder von einem übergeordneten Skript mit verschiedenen Browsern (durch übergebene Parameter) ausführen zu lassen. Somit haben wir nur einmal den Code des TestCases, aber die Möglichkeit es in verschiedenen Browsers auszuführen.
In Eclipse können wir über „Run Configurations“ die Argumente einstellen, die dem Testskript beim Ausführen übergeben werden.
In oberen Dialog befindet sich unten der Button „Run“. Wenn wir diesen „Run“-Button drücken, wird bei der Ausführung das Argument „Chrome“ übergeben und somit läuft der Testfall dann in Chrome.
Wir implementieren diese Browser-Unabhängigkeit so, dass man nicht gezwungen ist einen Browser als Skriptparameter zu übergeben. Wir implementieren Firefox als Default, falls kein Browser übergeben wird. Unsere Methode zum Setup des Browsers sieht wie folgt aus.
public static void init_Browser(String[] args) throws Exception { String browser = null; if (args.length == 0) { System.out.println("No Browser Parameter given, use default Browser Firefox"); browser = "Firefox"; } else { browser = args[0]; } if (browser.equalsIgnoreCase("Firefox")) { driver = new FirefoxDriver(); } else if (browser.equalsIgnoreCase("Chrome")) { String pathToChromeDriver = ".//ChromeDriver//chromedriver_Win_220.exe"; System.setProperty("webdriver.chrome.driver", pathToChromeDriver); driver = new ChromeDriver(); } else { System.out.println("Browser not defined!"); throw new Exception("Browser not defined!"); } driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS); }
Später können wir dies leicht auf eine bessere Art des Cross-Browser-Testing umstellen, indem wir zum Beispiel TestNG einbinden und darüber die Test-Parameter wählen oder TestNG als DatenProvider nutzen. Mit TestNG können wir dann später die Testfälle parallel in allen definierten Browsern gleichzeitig ausführen.
Mit der aktuellen Implementierung schaffen wir uns damit schon mal eine Basis und sind auch jetzt schon in der Lage, ein Testskript ohne Code Änderungen oder Code-Duplizierungen in verschiedenen Browsern zu testen.
Exkurs: Hinzufügen Selenium Java Doc in Eclipse
Eine Grundlegende Dokumentation von Funktionen wird in Eclipse durch importieren der Selenium-Libraries bereits gegeben. Allerdings kann man die Dokumentation noch stark erweitern. Hat man dies getan, sieht man in Eclipse direkt erweiterte Dokumentation. Hier am Beispiel der get-Methode.
Um diese erweiterten Java-Docs in Eclipse zuzufügen, gehen wir wie folgt vor. Als erstes kopieren wir uns den Link der Java Docs von der Selenium Download Page. In folgendem Screenshot ist der Link rot umrandet.
Diesen Pfad, ohne index.html, also in unseren Fall „http://seleniumhq.github.io/selenium/docs/api/java/“, kopieren wir nun in die Properties unseres Selenium Projekts. Dazu öffnen wir die Projekt Properties des Projekts in Eclipse über das Rechtklick-Kontextmenü. Dann geben wir, wie in folgendem Screenshot zu sehen, an dieser Stelle den Pfad ein. Wenn der Link hinein kopiert ist, können wir noch „Validate“ klicken, um prüfen zu lassen, ob alles funktioniert. Nicht vergessen das „indext.html“ aus dem Link zu entfernen. Dann alles mit ok bestätigen und die erweiterte Doku sollte nun vorhanden sein.
Selenium Testskript zum Login in WordPress
Mit unserer Basis, dem Öffnen eines gewünschten Browsers und starten der Webseite, wollen wir nun die ersten Aktionen auf der Webseite tätigen. Dazu wollen wir uns nach dem Öffnen der Frontpage zum Login/Register-Formular klicken und dort dann das Login-Formular auswählen. Um dies zu vollziehen, brauchen wir Dinge, um die Objekte in der Webseite zu Referenzieren. Dies kann eine ID oder Name im HTML Code sein oder ein XPath aus den XML-Knoten bzw. dem DOM Baum der Webseite. Das Addon Firebug sollten wir im Firefox installiert haben. Wir bekommen alle Infos auch ohne Firebug, aber wir finden dieses Addon dazu sehr komfortabel.
Automatisierung des Login/Register-Links mit Selenium
Beginnen wir mit dem Login/Register-Link in der oberen Haupt-Navigationsleiste. Wir machen einen Rechts-Klick auf den Login/Register-Link und wählen „Element mit Firebug untersuchen“.
Wie oben im Screenshot zu sehen, werden wir direkt zum passenden HTML Code geführt. Über Firebug könnten wir uns auch direkt den XPath zu einem Element kopieren lassen. Wir wollen uns aber etwas Robustes suchen, sodass wir eher selten eine Wartung der Testskripte bzw. Objekt-Referenzen brauchen. Bei unserer Webseite entscheiden wir uns bei diesem Link und auch bei den späteren Textfeldern dazu die „id“ zu nehmen. Wir kopieren uns somit aus Firebug den String „menu-item-826“.
Bei einem Einzeiler macht eine Methode nicht unbedingt Sinn, aber da wir das Testfalldesign von Anfang an von den Objekt-Referenzen und der Selenium Testautomatisierungstechnik trennen wollen, legen wir auch dafür eine eigene Methode an.
public static void mainNav_LinkLoginRegister_Click() { driver.findElement(By.id("menu-item-826")).click(); }
Da wir den Selenium „driver“ durchgehend brauchen, haben wir diesen in eine „static variable“ in der Klasse ausgelagert. Dazu später mehr, wenn man das ganze Skript sieht. Bei Methoden Aufruf wird ein Element gesucht, welches „By.id“, also über die ID, identifiziert wird. Und wir suchen, wie bereits oben im Firebug-Screenshot zu sehen, den Link anhand der konkreten ID „menu-item-826“. Das „.click()“ am Ende sorgt für den nötigen Klick.
Wenn wir diese Methode ausführen, wird also in der oberen Hauptnavigationsleiste der Link Login/Register geklickt, was auch durch den Methoden-Name erkenntlich sein soll „mainNav_LinkLoginRegister_Click()“.
Testautomatisierung des WordPress Login-Formulars mit Selenium
Das gleiche machen wir nun für das Formular in der Login/Register-Webseite. In dem Login-Formular haben wir einen „Benutzername“ und ein „Passwort“ in Input-Textfeldern anzugeben und wir haben einen „Anmelden“-Button, um das Formular abzusenden (submit).
Hier ein letztes Beispiel, wie man per Firebug nach passenden Attributen für Objektreferenzen sucht, am Beispiel des „Benutzername“-Input-Textfelds:
Wir finden für das Benutzername-Input-Textfeld die id=“user_login„, das ist für unsere Objekt-Referenzierung perfekt. Diese ID sollte auf der Seite damit einzigartig sein, dazu ist sie sehr aussagekräftig und sie muss bei kommenden Design Änderungen der Webseite wahrscheinlich nicht geändert werden. Sprich, auch wenn das Formular sich verschiebt oder verändert (und zB. der Xpath sich ändert) kann die ID dieses Textfelds gleich bleiben.
Für das Füllen und Absenden des Login-Formulares implementieren wir wieder eine neue Methode. Die restlichen benötigten IDs suchen wir uns nach beschriebenen Vorgehen mit Firebug komfortabel in aus der Webseite zusammen. Die komplette Methode sieht dann wie folgt aus, Titel „page_loginRegister_FormLogin_FillSend“. Mit dem Postfix „FillSend“ wollen wir ausdrücken, dass die Methode die Daten in die Textfelder einträgt und das Formular auch direkt absendet.
public static void page_loginRegister_FormLogin_FillSend() { /* Identify Element and take action with two lines of code */ WebElement element_UserName = driver.findElement(By.id("user_login")); element_UserName.sendKeys("TestUser"); /* Identify Element and take action with one line of code */ driver.findElement(By.id("user_pass")).sendKeys("xxxx"); driver.findElement(By.id("wp-submit")).submit(); /* verify logged-in correctly */ String fullBodyText = driver.findElement(By.tagName("body")).getText(); Assert.assertTrue(fullBodyText.contains("Sie sind bereits eingeloggt!"), "Login Text not found!"); }
In dem oberen Codebeispiel sehen wir auch, wie man ein Objekt in ein oder zwei Codezeilen identifiziert und ansprechen kann. Einmal wird in einer Codezeile das Objekt gesucht und dann in einer zweiten Codezeile benutzt (siehe /* Identify Element and take action with two lines of code */). Und wir sehen eine Alternative, die wir zuvor schon bei dem Link angewandt haben, in der wir alles in einer Codezeile machen (siehe /* Identify Element and take action with one line of code */).
„sendKeys()“ ist hierbei die Funktion, um Text in ein Eingabefeld einzutragen.
„submit()“ ist die Funktion, um ein Formular abzusenden. Sprich, ein „submit“ entspricht auf der Webseite dem Klick auf den Button „Anmelden“.
Unten in der Methode sehen wir noch einen Verifikationspunkt „Assert.assertTrue“. Dieser prüft, ob wir korrekt eingeloggt sind. Oft werden dazu Seitentitel, Images oder weitere Punkte geprüft. Wir begnügen uns mit einer Prüfung eines Text-Strings im Page-Content, der nur erscheint, wenn man sich auf der Webseite korrekt einloggt. Dazu speichern wir uns den kompletten body-Text in einer Variablen und suchen im nächsten Schritt, ob sich der gewünschte Text in dem „Body“ befindet.
Es folgt das aktuelle Skript als Gesamtes mit allen neuen Methoden:
tbCom_LoginDynamicBrowser.java
import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.openqa.selenium.chrome.ChromeDriver; public class tbCom_LoginDynamicBrowser { /* * @param args arg 0 = Browser: "Chrome", "Firefox" */ static WebDriver driver; public static void main(String[] args) throws Exception { init_Browser(args); start_TBcom(); mainNav_LinkLoginRegister_Click(); page_loginRegister_FormLogin_FillSend(); secNavi_LinkTestautomatisierung_Click(); } public static void init_Browser(String[] args) throws Exception { String browser = null; if (args.length == 0) { System.out.println("No Browser Parameter given, use default Browser Firefox"); browser = "Firefox"; } else { browser = args[0]; } if (browser.equalsIgnoreCase("Firefox")) { driver = new FirefoxDriver(); } else if (browser.equalsIgnoreCase("Chrome")) { String pathToChromeDriver = ".//ChromeDriver//chromedriver_Win_220.exe"; System.setProperty("webdriver.chrome.driver", pathToChromeDriver); driver = new ChromeDriver(); } else { System.out.println("Browser not defined!"); throw new Exception("Browser not defined!"); } driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS); } public static void start_TBcom() { String URL = "http://www.testing-board.com"; driver.get(URL); } public static void mainNav_LinkLoginRegister_Click() { driver.findElement(By.id("menu-item-826")).click(); } public static void page_loginRegister_FormLogin_FillSend() { /* Identify Element and take action with two lines of code */ WebElement element_UserName = driver.findElement(By.id("user_login")); element_UserName.sendKeys("TestUser"); /* Identify Element and take action with one line of code */ driver.findElement(By.id("user_pass")).sendKeys("xxxxxx"); driver.findElement(By.id("wp-submit")).submit(); /* verify logged-in correctly */ String fullBodyText = driver.findElement(By.tagName("body")).getText(); Assert.assertTrue(fullBodyText.contains("Sie sind bereits eingeloggt!"), "Login Text not found!"); } public static void secNavi_LinkTestautomatisierung_Click() { driver.findElement(By.id("menu-item-695")).click(); /* verify Page is loaded correctly */ String fullBodyText = driver.findElement(By.tagName("body")).getText(); Assert.assertTrue(fullBodyText.contains("Testautomatisierung ist ein automatisiertes Testverfahren"), "Text on Page Testautomatisierung not found!"); } }
In dem Skript befindet sich das Testfall-Design in der relativ kurzen Main-Methode. Die ganze Selenium Testautomatisierungstechnik und Objekt-Referenzen befinden sich in den wiederverwendbaren Methoden. Mit „keyword driven testing“ hat dies noch nicht viel zu tun, aber wir vermeiden bereits schon redundanten Code, wenn wir die gleichen Teststeps (für die wir Methoden erstellt haben), nun in weiteren Testfällen nutzen würden.
Exkurs: Auswahl Element-Identifizierung und „Design for Testability“.
Es gibt verschiedene Möglichkeiten den Link in der Main-Navigations-Leiste oder die Textfelder des Login-Formulars zu identifizieren. Zum Beispiel Position, den XPath, das Design, den Text, den Name, den Titel, die ID, etc.
Wir entschieden uns für die ID. Um es testbarer und weniger Wartungsintensiv zu machen, sollte im Falle des Login/Register-Links in der Main-Navigations-Leiste noch einen Bezeichner als Attribut hinzugefügt werden, der noch weniger Änderungsanfällig ist. In unserem Fall müssen wir dieses Objekt mit der ID „menu-item-826“ anpassen, wenn sich die Reihenfolge der Items in der Navigationsleiste ändert, da ein WordPress-Plugin die aktuell verwendete ID (menu-item-826) selbst vergibt.
Dies ist kein schönes „Design for Testability“. Im besten Fall gäbe es ein Attribut, zum Beispiel eine ID mit Bezeichner „Main-Navi-LoginRegister-Link“, welcher damit unabhängig von Position, Design oder angezeigten Text wäre. Für dieses Tutorial nutzen wir die vorhandene ID des übergeordneten List-items.
Für unser Tutorial ist das zwar zunächst unerheblich, für Ihre unternehmenseigene Testautomatisierung sollten Sie aber von Beginn an auf ein Mindestmaß an „Design for Testability“ setzen.
Bezüglich eines Responsive Design bedeutet dies, dass Elemente, die durch das Responsive Verhalten zum Beispiel die Position oder angezeigten Text verändert, noch die gleiche ID oder andere Attribute behalten können und sollten.
Exkurs: Wann brauchen wir Xpath?
XPath ist eine weitere Variante in Selenium (und auch eine gängige Methode in anderen Testautomatisierungstools), um Objekte zu identifizieren. Mit XPath können wir einen ganzen Pfad (XML-Knoten / DOM Baum) bis zu einem Element referenzieren. Dies hat den Vorteil wenn Elemente, die wir klicken wollen, nicht einzigartig sind. Oder falls eine Aktion mit einem Element an einer bestimmten Position geschehen soll, ohne dass wir Informationen über dessen Attribute haben. Genauso kann XPath angewandt werden, wenn Applikationen eher dynamisches IDs haben, aber der Ort gleich bleibt. XPath ist sehr mächtig in seinen Möglichkeiten Objekte zu referenzieren.
Man kann auch Objekte ausschließen, denen bestimmte Objekte folgen oder nur Objekte einschließen, die bestimmte Objekte als Vorgänger haben. Auch zum Durchsuchen von Tabellen in Zeilen und Spalten ist es gut geeignet. In unserem Fall, ist es aber nicht nötig und auch nicht angebracht. Unsere IDs sind einzigartig und werden dies auch vorerst bleiben. Und in der aktuellen Form, mit simpler Identifizierung durch die ID, ist es geschützt gegen Responsive Veränderungen, Browserwechsel und auch gegen Design Änderungen, solange die IDs gleich bleiben.
Selenium Tutorial Ausblick: Was kommt demnächst
Damit beenden wir das erste Selenium Tutorial mit folgendem Ausblick.
- Im nächsten Tutorial (Selenium Webdriver Tutorial 2), bewegen wir uns in kleinen Schritten weiter in Richtung hybrides Data-Driven und Keyword-Driven Testframework. Weiterhin werden wir kleinere Code-Verbesserungen in der Struktur umsetzen.
- In späteren Selenium Tutorials (Selenium Webdriver Tutorial 3-5), sehen wir Test Reporting mit TestNG aus Eclipse heraus, echtes Data-Driven über Excel und TestNG (Parameter, Dataprovider). Weiterhin bilden wir ein echtes Keyword-Driven Testframework in welchem Testfälle in Excel designt werden können.
- Selenium Testfälle über HP ALM 12 ausführen und das Testergebnis wieder zurück in ALM bekommen und dort anzeigen.
Geniale Zusammenfassung! Werde selber bald mit Selenium testen lernen und fühl mich nun deutlich besser vorbereitet – Dank!
Sehr gutes Tutorial. Leider scheinen die Login-Daten für die Testinstanz nicht mehr zu funktionieren.
An der Stelle sind im Selenium Tutorial sozusagen nur Platzhalter für den Login auf der Testinstanz eingefügt, nicht die echten Accountdaten. Das müsste man dann auf seine eigene WordPress Webseite mit HTTP Basic Auth übertragen.
Viel Spaß!
Hallo,
an sich ein gutes Tutorial, Beruflich habe ich schon mit Selenium IDE gearbeitet was ja ausschließlich über firefox läuft. (meines Wissens nach 🙂 )
Mir stellt sich die Frage ob es auch eine ähnliche Form für selbst geschriebene Apps gibt. Die im wesentlichen in ELECTRON und JAVASCRIPT geschrieben wurden? Bin mir unsicher ob Selnium WebDriver da ein richtiger Lösungsansatz für mich ist. Können Sie mir vielleicht weiter helfen?
Gruß Michael
Electron kannte ich zwar nicht, aber scheint mir bekannte Webelemnet (HTML, Javascript, CSS) zu nutzen. Nur dann eben nicht im Standard Browser, wenn ich es richtig verstehe, sondern eine eigene UI, welche aber wiederum auf Chromium basiert. Chromium ist der Google Browser Engine auf dem zum Beispiel Chrome (aber auch Opera mittlerweile) aufsetzt.
Wenn ich nach „electron selenium“ google, finde ich ein Selenium Tutorial in github von electron, das besagt, dass es einen eigenen Driver gibt (Spectron), der dann auf dem ChromeDriver von Selenium aufsetzt.
Scheint mir eine gute OpenSource Lösung, insofern die Zwischenschicht Spectron gut funktioniert. Selenium selbst sollte kein Problem haben, die Elemente zu automatisieren, die electron nutzt. Wobei ich mich, da ich gerade mal die Frontpage von electron gelesen habe, ggf. auch mit Halbwissen etwas weit aus dem Fenster lehne.
Ansonsten schau bei Bedarf auf unsere Testautomatisierungs-Tools Seite, falls es doch ein anderes Programm sein soll. Mit kommerziellen Programmen wie Ranorex (oder anderen) sollte das auch gehen.
https://www.testing-board.com/testautomatisierung-tools/
Bei Bedarf, einfach mal 3-4 Tools zur Automatisierung installieren und evaluieren. Electron klingt mir, durch die Webelemente, erst mal gut testbar. Aber am Ende ist es immer auch etwas „probieren“.
Viel Erfolg!
Sebastian
Die Klassenbibliothek „import org.openga.selenium.firefox.FirefoxDriver“ scheint zu fehlen.
Die Klasse start_Firefox.java kann leider nicht angelegt werden
Thank you for the detailed explanation of selenium webdriver tutorial. Looking forward to learn a lot from your articles.