menu
書いてる野郎
orebike@gmail.com
ページ自体をオブジェクトとして捉える設計方法らしく、Selenide でもそれを推奨している。
テスト対象画面に埋まっている要素はたくさんあると思うが、 それのチェックするポイントはその要素全部ではなく、チェックしたいのは画面の「機能」である。
ページオブジェクトとはこのチェックすべき機能を持つオブジェクトとなる。 ウェブページの Java クラス表現とも言っていいだろう。
例えば 「Google の検索ページ」があったとすると、その機能は「検索」であり、確認すべきはその結果である。
つまりこのオブジェクトは googleSearchPage.search(“hogehoge”);
が実装されており、それが正しく動作することを期待するということである。
そしてその結果は「検索結果一覧ページの PageObject」となる。
よって、テストするというのは、テキストボックスになにか入力されて、ボタンを押すとどうなるではなくて、 単純にこの PageObject の「検索メソッド」の挙動をテストするということになる。
つまり、どうしてくれるかを Page Object に定義し、それがどうなればいいかを個別のテストに実装するということになる。
テストするだけにはちょっと重厚過ぎで、この Page Object にバグが混入する気もするが、 この考え方は、ページの機能を Javaコードで厳密に定義するということなので非常によいと思う。
このようなエラーが出る場合があるが、
java.lang.RuntimeException: Failed to create new instance of class...
対象のクラスを内部クラスとして実装した場合宣言を
public static class HogePage{ }
このように静的に宣言しなければならない。
Google の検索ページを対象にするとするとこのようになる
// 検索画面を表す Page Object public static class GoogleSearchPage { // 検索画面の検索機能を表すメソッド public GoogleResultsPage search(String query) { // 画面の入力項目の DOM を掴む SelenideElement input = $("#lst-ib"); // 検索キーワードを入力する input.val(query); // 検索させる。 // サジェストがあるとボタンの挙動が変わるので // Enter で動作させている。 input.pressEnter(); // ここで画面が結果に切り替わるのだが // Selenide がそこはウマイこと同期してくれる。 // 切り替わった画面に対してまた Page Object を生成する。 return page(GoogleResultsPage.class); } } // 検索結果画面を表す Page Object public static class GoogleResultsPage { // 検索結果画面の検索結果部分を取得するためのメソッド public ElementsCollection getResultList() { return $$("#res .g"); } }
この中の Selenide の page
メソッドを使うことで、
実行した結果のページとクラスを関連付けてオブジェクト化することができる。
結果要素をさらにクラスでラップしていくとさらにわかりやすくなると思う。
↑で作ったクラスを使うには
このようになる。
GoogleSearchPage searchPage = open("https://www.google.co.jp/", GoogleSearchPage.class); GoogleResultsPage resultPage = searchPage.search("unko"); for(SelenideElement elm: resultPage.getResultList()) { System.out.println(elm.find("h3").getText()); }
open メソッドの第二引数にクラスを与えて対象のページとクラスを関連付けてオブジェクトを生成する。
つまり引数2個版の open というのは、これと同じということだ。
open("https://www.google.co.jp/"); GoogleSearchPage searchPage = page(GoogleSearchPage.class);