1概要

この記事では、Serenity BDDの脚本パターンについて簡単に説明します。この記事を読む前に、まず/serenity-bdd[Serenity BDDの基礎]リンクを読むことをお勧めします。また、

Serenity BDDとSpringの統合

に関する記事も興味深いかもしれません。

Serenity BDDで紹介されたScreenplayは、チームがより堅牢で信頼性の高いテストを作成できるようにすることで、優れたテスト習慣および適切に設計されたテストスイートを促進することを目的としています。これはSelenium WebDriverとPage Objectsモデルに基づいています。/java-selenium-with-junit-and-testng[Seleniumの紹介]を読んでいるのであれば、これらの概念はどちらかといえばおなじみでしょう。


2 Mavenの依存関係

まず、

pom.xml

ファイルに次の依存関係を追加しましょう。

<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-junit</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-screenplay</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-screenplay-webdriver</artifactId>
    <version>1.4.0</version>
</dependency>


serenity-screenplay

およびhttps://search.maven.org/classic/#searchの最新バージョン%7Cga%7C1%7Ca%3A%22serenity-screenplay-webdriver[serenity-screenplay-webdriver]はMaven Central Repositoryから取得できます。

私達はまたスクリーンショットを実行するためにウェブドライバーを必要とする –

ChromeDriver

またはhttps://github.com/mozilla/geckodriver/releases[Mozilla-GeckoDriver]しましょう。この記事では、ChromeDriverを使用します。

WebDriverを有効にするには、次のプラグイン設定が必要です。ここで、

webdriver.chrome.driver

の値は、mavenプロジェクトのChromeDriverバイナリファイルの相対パスにする必要があります。

<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.20</version>
    <configuration>
        <systemProperties>
            <webdriver.chrome.driver>chromedriver</webdriver.chrome.driver>
        </systemProperties>
    </configuration>
</plugin>


3 Webドライバのサポート

WebDriver変数に

@ Managed

アノテーションを付けることでSerenityにWebDriverインスタンスを管理させることができます。 Serenityは各テストの開始時に適切なドライバを開き、テストが終了したらシャットダウンします。

次の例では、ChromeDriverを起動し、Googleを開いて「baeldung」を検索します。検索結果にオイゲンの名前が表示されることを期待しています。

@RunWith(SerenityRunner.class)
public class GoogleSearchLiveTest {

    @Managed(driver = "chrome")
    private WebDriver browser;

    @Test
    public void whenGoogleBaeldungThenShouldSeeEugen() {
        browser.get("https://www.google.com/ncr");

        browser
          .findElement(By.name("q"))
          .sendKeys("baeldung", Keys.ENTER);

        new WebDriverWait(browser, 5)
          .until(visibilityOfElementLocated(By.cssSelector(".__ksh")));

        assertThat(browser
          .findElement(By.cssSelector(".__ksh"))
          .getText(), containsString("Eugen (Baeldung)"));
    }
}


@ Managed

にパラメータを指定しない場合、Serenity BDDはこの場合Firefoxを使用します。

@ Managed

アノテーションでサポートされているドライバの全リスト:

firefox、chrome、iexplorer、htmlunit、phantomjs

IExplorerまたはEdgeでテストする必要がある場合は、http://selenium-release.storage.googleapis.com/index.html[here(for IE)]およびhttps://developer.microsoft.comからWebドライバをダウンロードできます。/en-us/microsoft-edge/tools/webdriver[ここ(Edge用)]。 Safari WebDriverはMacOSの

/usr/bin/safaridriver

でのみ利用可能です。


4ページオブジェクト

Serenity Page ObjectsはWebDriverページオブジェクトを表します。


PageObject


は、再利用のためにWebDriverの詳細を隠します。


4.1.

PageObject


を使用したリファクタリングの例

まず、エレメントの検索、検索、結果検証の各アクションを抽出することによって、http://thucydides.info/docs/apidocs/net/thucydides/core/pages/PageObject.html[

PageObject

]を使用して、以前のテストを改良しましょう。

@DefaultUrl("https://www.google.com/ncr")
public class GoogleSearchPageObject extends PageObject {

    @FindBy(name = "q")
    private WebElement search;

    @FindBy(css = ".__ksh")
    private WebElement result;

    public void searchFor(String keyword) {
        search.sendKeys(keyword, Keys.ENTER);
    }

    public void resultMatches(String expected) {
        assertThat(result.getText(), containsString(expected));
    }
}



WebElement


はHTML要素を表します。インターフェースのAPIを通してWebページと対話することができます。上記の例では、ページ内でWeb要素を見つける方法として、要素名と要素のCSSクラスの2つを使用しました。

タグ名による検索、リンクテキストによる検索など、Web要素を検索するときの適用方法は他にもあります。 。


WebElement

をhttp://thucydides.info/docs/apidocs/net/thucydides/core/pages/WebElementFacade.html[

WebElementFacade

]に置き換えることもできます。これにより、Web要素を扱うためのより流暢なAPIが提供されます。

  • SerenityはJUnitテスト** の

    PageObject

    フィールドを自動的にインスタンス化するので、以前のテストはもっときれいなものに書き換えることができます。

@RunWith(SerenityRunner.class)
public class GoogleSearchPageObjectLiveTest {

    @Managed(driver = "chrome")
    private WebDriver browser;

    GoogleSearchPageObject googleSearch;

    @Test
    public void whenGoogleBaeldungThenShouldSeeEugen() {
        googleSearch.open();

        googleSearch.searchFor("baeldung");

        googleSearch.resultMatches("Eugen (Baeldung)");
    }
}

これで、他のキーワードを使用して検索し、

GoogleSearchPageObject

に変更を加えることなく関連する検索結果と一致させることができます。


4.2. 非同期サポート

今日では、多くのWebページが動的に提供またはレンダリングされています。そのような場合に対処するために、

PageObject

は要素の状態を調べることを可能にする多くの豊富な機能もサポートします。要素が表示されているかどうかを確認するか、表示されるまで待ってから先に進むことができます。

表示したい要素が表示されるようにして、

resultMatches

メソッドを強化しましょう。

public void resultMatches(String expected) {
    waitFor(result).waitUntilVisible();
    assertThat(result.getText(), containsString(expected));
}

あまり長く待つ必要がない場合は、待機中のタイムアウトを明示的に指定できます。

public void resultMatches(String expected) {
    withTimeoutOf(5, SECONDS)
      .waitFor(result)
      .waitUntilVisible();
    assertThat(result.getText(), containsString(expected));
}


5脚本パターン

脚本パターンは、SOLID設計原則を自動受け入れテストに適用します。脚本パターンの一般的な理解は、

given

when

then

コンテキストで次のように説明できます。


  • given

    – 何らかのタスクを実行できる

    Actor


  • when



    Actor



    Task

    を実行します


  • the –

    the

    Actor

    は効果を確認し、結果を確認する必要があります

Googleを使用できるユーザーKittyがGoogleで「baeldung」を検索すると、Kittyは結果にEugenの名前を表示するはずです。

まず、Kittyが実行できるタスクを定義します。

  1. キティはグーグルを使用することができます.

+[source、java、gutter:、true]

public class StartWith implements Task {

    public static StartWith googleSearchPage() {
        return instrumented(StartWith.class);
    }

    GoogleSearchPage googleSearchPage;

    @Step("{0} starts a google search")
    public <T extends Actor> void performAs(T t) {
        t.attemptsTo(Open
          .browserOn()
          .the(googleSearchPage));
    }
}

  1. KittyはGoogleで検索することができます.

+[source、java、gutter:、true]

public class SearchForKeyword implements Task {

    @Step("{0} searches for '#keyword'")
    public <T extends Actor> void performAs(T actor) {
        actor.attemptsTo(Enter
          .theValue(keyword)
          .into(GoogleSearchPage.SEARCH__INPUT__BOX)
          .thenHit(Keys.RETURN));
    }

    private String keyword;

    public SearchForKeyword(String keyword) {
        this.keyword = keyword;
    }

    public static Task of(String keyword) {
        return Instrumented
          .instanceOf(SearchForKeyword.class)
          .withProperties(keyword);
    }
}

  1. キティはGoogleの検索結果を見ることができます.

public class GoogleSearchResults implements Question<List<String>> {

    public static Question<List<String>> displayed() {
        return new GoogleSearchResults();
    }

    public List<String> answeredBy(Actor actor) {
        return Text
          .of(GoogleSearchPage.SEARCH__RESULT__TITLES)
          .viewedBy(actor)
          .asList();
    }
}

また、Google検索

PageObject

を既に定義しています。

@DefaultUrl("https://www.google.com/ncr")
public class GoogleSearchPage extends PageObject {

    public static final Target SEARCH__RESULT__TITLES = Target
      .the("search results")
      .locatedBy(".__ksh");

    public static final Target SEARCH__INPUT__BOX = Target
      .the("search input box")
      .locatedBy("#lst-ib");
}

今私たちの主なテストクラスはようになります。

@RunWith(SerenityRunner.class)
public class GoogleSearchScreenplayLiveTest {

    @Managed(driver = "chrome")
    WebDriver browser;

    Actor kitty = Actor.named("kitty");

    @Before
    public void setup() {
        kitty.can(BrowseTheWeb.with(browser));
    }

    @Test
    public void whenGoogleBaeldungThenShouldSeeEugen() {
        givenThat(kitty).wasAbleTo(StartWith.googleSearchPage());

        when(kitty).attemptsTo(SearchForKeyword.of("baeldung"));

        then(kitty).should(seeThat(GoogleSearchResults.displayed(),
          hasItem(containsString("Eugen (Baeldung)"))));
    }
}

このテストを実行した後、テストレポートで実行された各ステップのスクリーンショットがKittyに表示されます。

リンク:/uploads/kitty-search-baeldung.png%20930w[]


6. 概要

この記事では、Serenity BDDでScreenplay Patternを使用する方法を紹介しました。また、

PageObject

の助けを借りて、WebDriversと直接対話する必要がないため、テストを読みやすく、保守し、拡張することが容易になります。

Serenity BDDの

PageObject

と脚本パターンの詳細については、Serenityのドキュメントの関連セクションをご覧ください。

いつものように、完全なサンプルコードはhttps://github.com/eugenp/tutorials/tree/master/libraries[the Github]にあります。