1. 序章

この記事では、以前の記事に基づいて構築し、ページオブジェクトパターンを導入することでSelenium/WebDriverテストを改善し続けます。

2. セレンの追加

プロジェクトに新しい依存関係を追加して、より単純で読みやすいアサーションを記述しましょう。

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
</dependency>

最新バージョンは、 Maven CentralRepositoryにあります。

2.1. 追加の方法

シリーズの最初のパートでは、ここでも使用するいくつかの追加のユーティリティメソッドを使用しました。

navigateTo(String url)メソッドから始めます。これは、アプリケーションのさまざまなページをナビゲートするのに役立ちます。

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

次に、 clickElement(WebElement element) –名前が示すように–は、指定された要素に対してクリックアクションを実行します。

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

3. ページオブジェクトパターン

Selenium は、HTMLページとの対話に使用できる強力な低レベルAPIを多数提供します。

ただし、テストの複雑さが増すにつれて、DOMの低レベルの生の要素との対話は理想的ではありません。 私たちのコードは変更が難しく、UIを少し変更すると壊れてしまう可能性があり、簡単に言えば柔軟性が低下します。

代わりに、単純なカプセル化を利用して、これらの低レベルの詳細をすべてページオブジェクトに移動できます。

最初のページのオブジェクトを書き始める前に、パターンを明確に理解しておくことをお勧めします。これにより、ユーザーとアプリケーションの相互作用をエミュレートできるようになります。

ページオブジェクトは一種のインターフェースとして動作し、ページまたは要素の詳細をカプセル化し、その要素またはページと対話するための高レベルAPIを公開します。

そのため、重要な詳細は、メソッドのわかりやすい名前を提供することです(例: clickButton()、navigateTo())。これは、ユーザーが実行したアクションを複製するのが簡単であり、通常、ステップをチェーン化するときにAPIが向上するためです。

では、先に進んで、ページオブジェクトを作成しましょう。この場合は、ホームページです。

public class BaeldungHomePage {

    private SeleniumConfig config;
 
    @FindBy(css = ".nav--logo_mobile")
    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;
    }
}

実装がDOMの低レベルの詳細を処理し、優れた高レベルのAPIを公開していることに注目してください。

たとえば、 @FindBy アノテーションを使用すると、 WebElements を事前入力できます。これは、 ByAPIを使用して表すこともできます。

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

もちろん、どちらも有効ですが、注釈を使用する方が少しわかりやすくなります。

また、連鎖に注意してください– clickOnStartHere()メソッドは StartHerePage オブジェクトを返します–ここで相互作用を続けることができます:

public class StartHerePage {

    // Includes a SeleniumConfig attribute

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

    // constructor

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

簡単なテストを書いてみましょう。ここでは、ページに移動して要素の1つを確認します。

@Test
public void givenHomePage_whenNavigate_thenShouldBeInStartHere() {
    homePage.navigate();
    StartHerePage startHerePage = homePage.clickOnStartHere();
 
    assertThat(startHerePage.getPageTitle(), is("Start Here"));
}

私たちのホームページには以下の責任があることを考慮することが重要です。

  1. 指定されたブラウザ構成に基づいて、ページに移動します。
  2. そこで、ページのコンテンツ(この場合はタイトル)を検証します。

私たちのテストは非常に簡単です。 ホームページに移動し、「ここから開始」要素をクリックして、同じ名前のページに移動します。最後に、タイトルが存在することを確認します。

テストの実行後、 close()メソッドが実行され、ブラウザが自動的に閉じられます。

3.1. 懸念の分離

私たちが考慮できるもう1つの可能性は、懸念を分離することです(さらに)。2つの別々のクラスを持つことで、1つは私たちのすべての属性(WebElementまたはBy)を持つことになります。ページ:

public class BaeldungAboutPage {

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

もう1つは、テストする機能のすべての実装を処理します。

public class BaeldungAbout {

    private SeleniumConfig config;

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

    // navigate and getTitle methods
}

属性をByとして使用していて、注釈機能を使用していない場合は、インスタンス化されないように、ページクラスにプライベートコンストラクターを追加することをお勧めします。

前の例でthisキーワードを渡したのとは対照的に、この場合はBaeldungAboutPageクラスに注釈を含むクラスを渡す必要があることに注意してください。

@Test
public void givenAboutPage_whenNavigate_thenTitleMatch() {
    about.navigateTo();
 
    assertThat(about.getPageTitle(), is("About Baeldung"));
}

実装でページを操作するための内部の詳細をすべて保持できることに注目してください。ここでは、このクライアントを高レベルで読み取り可能なレベルで実際に使用できます。

4. 結論

このクイックチュートリアルでは、Page-Object Pattern を使用して、 Selenium/WebDriverの使用法を改善することに焦点を当てました。 パターンを利用してサイトと対話する実際的な方法を確認するために、さまざまな例と実装を実行しました。

いつものように、これらすべての例とスニペットの実装は、GitHubにあります。 これはMavenベースのプロジェクトであるため、インポートと実行が簡単である必要があります。