SeleniumのPageObjectパターンを学ぶ
SeleniumにおけるPageObjectパターンとは、ページを1つのオブジェクトとしてとらえるデザインパターンの1種のこと。
PageObjectパターンを使用してSeleniumを使ったテストスイートを構築することで、コードの重複化を防ぐことができる。
PageObjectパターンを実装するために、以下の6点に注意を払おう。
- publicメソッドはそのページが提供するサービスを現すようにする(The public methods represent the services that the page offers)
- ページの内部を露出させないように心がける(Try not to expose the internals of the page)
- 一般的には、アサーションは使用しない(Generally don't make assertions)
- メソッドはその他のPageObjectを返す(Methods return other PageObjects)
- ページ全体を表現するする必要はない(Need not represent an entire page)
- 同じアクションで違う結果が生じる場合は、別々のメソッドとしてモデル化しよう(Different results for the same action are modelled as different methods)
試しにGoogleのTOPページ(https://www.google.co.jp/)と検索結果ページをPageObject化してみる。
GoogleのTOPページ(GoogleSearchPage.java)
public class GoogleSearchPage { protected final WebDriver driver; @FindBy(name = "q") @CacheLookup private WebElement searchBox; /** * コンストラクタ * * @param driver */ public GoogleSearchPage(WebDriver driver) { this.driver = driver; } /** * PageFactoryを使用してWebElementをマッピングする * @return */ public GoogleSearchPage initialize() { // googleのトップページへ this.driver.get("https://www.google.co.jp/"); return PageFactory.initElements(this.driver, GoogleSearchPage.class); } /** * 検索ボックスにクエリを設定する * @param query */ private void setSearchBox(String query) { this.searchBox.clear(); this.searchBox.sendKeys(query); } /** * 画面遷移が完了するまでwait */ public void waitForPageLoad(final String currentTitle) { Wait<WebDriver> wait = new WebDriverWait(driver, 10); ExpectedCondition<Boolean> condition = new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { return !currentTitle.equals(driver.getTitle()); } }; wait.until(condition); } /** * 検索を行う * @param query */ public GoogleSearchResultPage search(String query) { final String currentTitle = driver.getTitle(); this.setSearchBox(query); this.searchBox.submit(); this.waitForPageLoad(currentTitle); return new GoogleSearchResultPage(this.driver).initialize(); } }
検索結果ページ(GoogleSearchResultPage.java)
public class GoogleSearchResultPage { protected final WebDriver driver; @FindBy(className = "vsc") @CacheLookup private List<WebElement> results; /** * コンストラクタ * @param driver */ public GoogleSearchResultPage(WebDriver driver) { this.driver = driver; } /** * PageFactoryを使用してWebElementをマッピングする * @return */ public GoogleSearchResultPage initialize() { return PageFactory.initElements(this.driver, GoogleSearchResultPage.class); } /** * 検索結果のWebElementを返す * @return */ public List<WebElement> getResults() { return this.results; } /** * ページのタイトルを返す * @return */ public String getPageTitle() { return this.driver.getTitle(); } }
この2つのクラスを利用して、「hoge」でググって検索結果が表示されていることをテストしてみる。
テストコード(JUnit4)
public class GoolgeTestCase { private WebDriver driver; @Before public void setUp() { this.driver = new FirefoxDriver(); } @After public void tearDown() { this.driver.quit(); } @Test public void hogeでGoogleで検索する() { final String query ="hoge"; GoogleSearchPage googleSearchPage = new GoogleSearchPage(this.driver).initialize(); GoogleSearchResultPage googleSearchResultPage = googleSearchPage.search("hoge"); // 検索結果ページのタイトルにhogeが含まれていること assertThat(googleSearchResultPage.getPageTitle(), is(containsString(query))); // 検索結果が0以上あること assertThat(googleSearchResultPage.getResults().size(), is(greaterThan(0))); } }