Testen mit Selenium/WebDriver und dem Page Object Pattern

Testen mit Selenium / WebDriver und dem Seitenobjektmuster

1. Einführung

In diesem Artikel bauen wir aufprevious writeup auf und verbessern unsere Selenium / WebDriver-Tests weiter, indem wir das Seitenobjektmuster einführen.

2. Selen hinzufügen

Fügen wir unserem Projekt eine neue Abhängigkeit hinzu, um einfachere, besser lesbare Aussagen zu schreiben:


    org.hamcrest
    hamcrest-all
    1.3

Die neueste Version finden Sie inMaven Central Repository.

2.1. Zusätzliche Methoden

Im ersten Teil der Serie haben wir einige zusätzliche Dienstprogrammmethoden verwendet, die wir auch hier verwenden werden.

Wir beginnen mit dernavigateTo(String url)-Methode, mit deren Hilfe wir durch verschiedene Seiten der Anwendung navigieren können:

public void navigateTo(String url) {
    driver.navigate().to(url);
}

Dann übernimmtclickElement(WebElement element) - wie der Name schon sagt - die Klickaktion für ein bestimmtes Element:

public void clickElement(WebElement element) {
    element.click();
}

3. Seitenobjektmuster

Selenium bietet uns viele leistungsstarke APIs auf niedriger Ebene, mit denen wir mit der HTML-Seite interagieren können.

Da die Komplexität unserer Tests jedoch zunimmt, ist die Interaktion mit den einfachen, unformatierten Elementen des DOM nicht ideal. Unser Code wird schwieriger zu ändern sein, nach kleinen Änderungen an der Benutzeroberfläche möglicherweise nicht mehr funktionieren und einfacher gesagt weniger flexibel sein.

Stattdessen können wir die einfache Kapselung verwenden und all diese Details auf niedriger Ebene in ein Seitenobjekt verschieben.

Bevor wir mit dem Schreiben unseres Objekts auf der ersten Seite beginnen, ist es gut, ein klares Verständnis des Musters zu haben, da es uns ermöglichen sollte, die Interaktion eines Benutzers mit unserer Anwendung zu emulieren.

Das Seitenobjekt verhält sich als eine Art Schnittstelle, die die Details unserer Seiten oder Elemente einschließt und eine API auf hoher Ebene zur Interaktion mit diesem Element oder dieser Seite bereitstellt.

Daher ist es ein wichtiges Detail, beschreibende Namen für unsere Methoden anzugeben (z. B. clickButton(), navigateTo()), da es für uns einfacher wäre, eine vom Benutzer ergriffene Aktion zu replizieren, und dies im Allgemeinen zu einer besseren API führt, wenn wir Schritte miteinander verketten.

Ok, jetzt gehen wir weiter undcreate our page object - in diesem Fall unsere Homepage:

public class exampleHomePage {

    private SeleniumConfig config;

    @FindBy(css=".header--menu > a")
    private WebElement title;

    @FindBy(css = ".menu-start-here > a")
    private WebElement startHere;

    // ...

    public StartHerePage clickOnStartHere() {
        config.clickElement(startHere);

        StartHerePage startHerePage = new StartHerePage(config);
        PageFactory.initElements(config.getDriver(), startHerePage);

        return startHerePage;
    }
}

Beachten Sie, wie unsere Implementierung mit den Details auf niedriger Ebene des DOM umgeht und eine nette API auf hoher Ebene verfügbar macht.

Mit der Annotation@FindBy können wir beispielsweise unsereWebElements vorab ausfüllen. Dies kann auch mithilfe der APIBy dargestellt werden:

private WebElement title = By.cssSelector(".header--menu > a");

Natürlich sind beide gültig, jedoch ist die Verwendung von Anmerkungen etwas sauberer.

Beachten Sie auch die Verkettung - unsere MethodeclickOnStartHere()gibt ein ObjektStartHerePagezurück -, mit der wir die Interaktion fortsetzen können:

public class StartHerePage {

    // Includes a SeleniumConfig attribute

    @FindBy(css = ".page-title")
    private WebElement title;

    // constructor

    public String getPageTitle() {
        return title.getText();
    }
}

Schreiben wir einen kurzen Test, bei dem wir einfach zur Seite navigieren und eines der Elemente überprüfen:

@Test
public void givenHomePage_whenNavigate_thenShouldBeInStartHere() {
    homePage.navigate();
    StartHerePage startHerePage = homePage.clickOnStartHere();

    assertThat(startHerePage.getPageTitle(), is("Start Here"));
}

Es ist wichtig zu berücksichtigen, dass unsere Homepage die Verantwortung hat für:

  1. Navigieren Sie auf der Grundlage der angegebenen Browserkonfiguration zu der Seite.

  2. Überprüfen Sie dort den Inhalt der Seite (in diesem Fall den Titel).

Unser Test ist sehr einfach; Wir navigieren zur Startseite, führen den Klick auf das Element „Start Here“ aus, um zur gleichnamigen Seite zu gelangen, und bestätigen schließlich, dass der Titel vorhanden ist.

Nach dem Ausführen unserer Tests wird die Methodeclose()ausgeführt, und unser Browser sollte automatisch geschlossen werden.

3.1. Bedenken trennen

Eine andere Möglichkeit, die wir in Betracht ziehen können, könnte darin bestehen, Bedenken zu trennen (noch mehr). Wenn zwei Klassen getrennt sind, kümmert sich eine um alle Attribute(WebElement oderBy) unserer Seite:

public class exampleAboutPage {

    @FindBy(css = ".page-header > h1")
    public static WebElement title;
}

Der andere wird dafür sorgen, dass alle Funktionen implementiert werden, die wir testen möchten:

public class exampleAbout {

    private SeleniumConfig config;

    public exampleAbout(SeleniumConfig config) {
        this.config = config;
        PageFactory.initElements(config.getDriver(), exampleAboutPage.class);
    }

    // navigate and getTitle methods
}

Wenn wir Attribute alsBy verwenden und die Anmerkungsfunktion nicht verwenden, wird empfohlen, unserer Seitenklasse einen privaten Konstruktor hinzuzufügen, um zu verhindern, dass er instanziiert wird.

Es ist wichtig zu erwähnen, dass wir die Klasse, die die Anmerkungen enthält, in diesem Fall an dieexampleAboutPage-Klasse übergeben müssen, im Gegensatz zu dem, was wir in unserem vorherigen Beispiel getan haben, indem wir das Schlüsselwortthisübergeben haben.

@Test
public void givenAboutPage_whenNavigate_thenTitleMatch() {
    about.navigateTo();

    assertThat(about.getPageTitle(), is("About example"));
}

Beachten Sie, dass wir jetzt alle internen Details für die Interaktion mit unserer Seite in der Implementierung beibehalten können. Hier können wir diesen Client tatsächlich auf einer hohen, lesbaren Ebene verwenden.

4. Fazit

In diesem kurzen Tutorial haben wir uns darauf konzentriert, die Verwendung vonSelenium/WebDriver with the help of the Page-Object Pattern zu verbessern. Wir haben verschiedene Beispiele und Implementierungen durchgesehen, um die praktischen Möglichkeiten zur Verwendung des Musters für die Interaktion mit unserer Site zu untersuchen.

Wie immer kann die Implementierung all dieser Beispiele und Snippets inover on GitHub gefunden werden. Dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.