GUI-Tests mit Selenium

IFS-Logo Diese Seite ist ein Teil der IsyFact-Standards. Alle Inhalte der Seite, insbesondere Texte und Grafiken, sind urheberrechtlich geschützt. Alle urheberrechtlichen Nutzungs- und Verwertungsrechte liegen beim Bundesverwaltungsamt.

Creative Commons Namensnennung Die Nutzung ist unter den Lizenzbedingungen der Creative Commons Namensnennung 4.0 International gestattet.

Selenium ist ein Open Source Werkzeug zur Automatisierung von Browser-Applikationen. Es zählt seit vielen Jahren zu den bekanntesten und beliebtesten UI Testautomatisierungslösungen für Webanwendungen. In erster Linie ist Selenium für die Automatisierung von Webanwendungen zu Testzwecken gedacht, kann jedoch auch für weitere, operative Aufgaben sinnvoll eingesetzt werden. So können mittels Selenium viele sich wiederholende Aufgaben bei der Administration webbasierter Anwendungen automatisiert werden. Ebenfalls findet Selenium immer stärkeren Einsatz bei Automatisierung der komplexen operativen Geschäftsprozesse mittels „Robotic Process Automation“ (RPA) Lösungen.

1. Setup

Zum Aufsetzen von Selenium und dem Erstellen von webbasierten GUI-Tests mit Selenium, sollte die ausführliche Entwickler-Dokumentation von Selenium herangezogen werden:

1.1. Selenium installieren

In Maven: selenium-java dependency in die pom.xml einfügen:

Listing 1. Einbindung von Selenium in der pom.xml
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>${selenium.version}</version>
    <scope>test</scope>
</dependency>

In Gradle: selenium-java dependency in die build.gradle des Projektes einfügen:

Listing 2. Einbindung von Selenium in der pbuild.gradle
dependencies {
compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '4.0.0'

1.2. Browser Drivers installieren

Die Browser Driver zur Unterstützung der Browser für Selenium werden von den jeweiligen Herstellern entwickelt und sind nicht Teil der Standard Selenium Distribution. Empfohlen wird an dieser Stelle der Firefox Browser:

Listing 3. Einbindung von Selenium Browser addons in der pom.xml
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-firefox-driver</artifactId>
    <version>${selenium.version}</version>
    <scope>test</scope>
</dependency>

1.3. Browser öffnen und schließen

Selenium 4 benötigt die Firefox Version 78 oder höher!

Listing 4. Browser öffnen und schließen
// create custom Firefox options
FirefoxOptions options = new FirefoxOptions();

// open Browser
WebDriver driver = new FirefoxDriver(options);

// close Brower
driver.quit();

2. Problematiken

Trotz der Beliebtheit bei UI Testautomatisierungslösungen für Webanwendungen ist Selenium kein vollwertiges Test-Framework! Das zeigt sich in folgenden Dimensionen:

2.1. Testen

  • Selenium stellt keine Assertions bereit, sondern kümmert sich um die reine UI-Automatisierung

  • Selenium liefert keine Integration in JUnit

  • Die Testkonfiguration kann komplex sein

2.2. Allgemein

  • Selenium ist ein DOM basiertes (Java-) Interface zum Browser. Daher ist ein Verständnis von HTML/CSS erforderlich, um automatisierte Abläufe zu beschreiben

  • In Selenium werden nur Referenzen von DOM Elementen gehalten, nichts wird zwischen gespeichert

  • Selenium adressiert die Asynchronität des Browsers nur oberflächlich

3. Best Practices

Zu den oben genannten Problemen gibt es Best Practices, mit denen man diesen entgegen wirken kann.

3.1. Assertions

Assertions mit Selenium sind für WebElement-Typen erstmal nicht möglich. Allerdings lassen sich die Values oder andere inhaltliche Werte und ihre primitiven Datentypen mittels Standard Assertions vergleichen:

Listing 5. Tests mit Selenium
import org.junit.Assert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDrive

[...]

@Test
public void testAssertFunctions() {
    // Driver setup
    System.setProperty("webdriver.chrome.driver", {$uri-to-driver}\\chromedriver.exe");
    WebDriver driver = new ChromeDriver();

    // Driver navigation
    driver.navigate().to("https://www.url.com/");

    String ActualTitle = driver.getTitle(); // returns the titel as a String
    String ExpectedTitle = "Most Reliable App & Cross Browser Testing Platform | BrowserStack";

    // String assertions
    Assert.assertEquals(ExpectedTitle, ActualTitle);

    // Get web element checkbox
    WebElement checkbox = driver.findElement(By.cssSelector("input[id*='StayLoggedInCheckbox']"));

    // Boolean assertions
    Assert.assertFalse(checkbox.isSelected());
    // isSelected returns primitive datatype boolean which we can assert

    // close browser
    driver.quit();

}

3.2. WebElement Finding bei asynchronen Änderungen

Grundlegende Informationen, wie man WebElemente über Selenium findet:

Sollten Probleme bei der Suche nach WebElement-Ids entstehen (z.B. da diese dynamisch generiert werden), kann auf zwei alternative Möglichkeiten zurückgegriffen werden:

3.2.1. XPath

XPath ist eine Alternative zum WebElement-Finding per ID. Es handelt sich dabei um die XML Path Language, die Teile eines XML-Dokumentes adressieren und auswerten kann. Da HTML und XML eine ähnliche Struktur haben, fällt es Selenium leicht, bei statischem HTML-Aufbau ein Web-Element über XPath zu finden.

    WebElement checkbox = driver.findElement(
                    By.xpath("/html/body/div[2]/div[1]/div/h4[1]/b/html[1]/body[1]/div[2]/div[1]/div[1]/h4[1]/b[1]"));

Aber auch die XPath-Pfade können durch die Asynchronität des Browsers oder durch dynamische Generierung ihr Ziel verfehlen.

3.2.2. Css Selector

Etwas sicherer und eventuell beständiger ist der Css Selector. Beispiel:

<input id="name"...>

wird generiert zu:

<input id="j_id1234567:name"...>

Die Suche nach dem WebElement mittels Selenium würde dann wie folgt aussehen:

driver.findElement(By.cssSelector("input[id^='j_id'][id$='name']"));

Das bedingt natürlich, dass die dynamischen IDs wenigstens zum Teil statisch sind, bzw. statische Komponenten wie bspw. name beinhalten.