Page Object Design Pattern(ページオブジェクトパターン)
ドキュメントに少し解説あり。
Page Object Design Pattern
・ページオブジェクトパターンで実装すると何が良いのか
・ページ操作とシナリオの分離
・メンテナンス性の向上
・テストケースの追加コストが低い(既にあるページオブジェクトを使える場合)
・なぜ、ページオブジェクトパターンか
ページオブジェクトパターンを知る前に100ケースほどテストを書いたのですが、サービスがアップデートされるたびに、シナリオとページ操作がぐっちゃぐちゃになっているテストコードから修正点を探し出すという、非常にバカなことをやっていました。
もちろん、漏れが起きるため、テストを回して修正、テストを回して修正、、、
一方、ページオブジェクトパターンで実装すれば、サービスがアップデートされれば、該当するページのテストを書き換えるだけで修正ができます。
もちろん、アップデートに伴い、シナリオを変更する必要も出てくるが、シナリオとページ操作が分離されているので、修正が容易でした。
ページオブジェクトパターンのメリットは、1度実装したページは使い回しが効くということです。
同じページ操作が複数のシナリオ内で出現することは、良くあること。。。
パターンで実装していなかった場合は、変なメソッドにまとめてしまったり、コピペで使いまわしたり。工数もかかるし、メンテナンス性は最悪というか皆無(笑・・えない)。
実際、シナリオ・ページ操作ぐっちゃぐちゃのテストケースを100個書いた後に、パターンに則って300ぐらい実装して身に染みた。
・書いたもの
・ページオブジェクトで使うインターフェース
・テストシナリオで必要となるページオブジェクト
・テストシナリオ
・テストデータを格納するYaml
・実際に使用しているインターフェース
public interface PageObject_Admin { //URL直叩き用 public void Open(); //未定 public void Close(); //各ページからログアウトするために public void Logout(); //トップページへのリンク public void Top(); //ヘルプ public void Help(); }
・ページ実装
public class PageObject001 implements PageObject_Master { static WebDriver driver; public PageObject001 () { driver = CreateDriverInstance.getDriver(); } // URL直叩き用 public void Open() { Extract_Driver.openBaseHTTP("/form/"); } // ログアウト用 public void Logout() { Extract_Auth.ToolLogout(); } public void Close() { } //トップへの遷移用 public void Top() { driver.findElement(By.linkText("トップ")).click(); Extract_Wait.FooterArrivalWait(); } public void Help() { } // タイトル public void inputComment_title(String Comment_title) { Extract_Input.SendKeysANDClear(By.id("title"),Comment_title); } // 本文 public void inputComment_body(String Comment_body) { Extract_Input.SendKeysANDClear(By.id("body"),Comment_body); } // 変更する public void doChange() { driver.findElement(By.id("change_submit")).click(); Extract_Wait.FooterArrivalWait(); driver.findElement(By.id("do_change")).click(); Extract_Wait.FooterArrivalWait(); driver.findElement(By.linkText("トップへ戻る")).click(); Extract_Wait.FooterArrivalWait(); } }
・テストシナリオ
public class TextCase0001 extends TestBase { @DataPoints public static Object[] getDataPoints() { // TODO getStackTraceは重いので、他の取得方法に変えたい。 String ClassInfo = Thread.currentThread().getStackTrace()[1] .getClassName(); return Extract_Yaml.ImportTestDataYaml_MAP(ClassInfo); } @Theory public void ゴニョゴニョする(Map<Object, Object> TestDataMAP) { PageObject001 PageObject001 = new PageObject001(); PageObject002 PageObject002 = new PageObject002(); PageObject003 PageObject003 = new PageObject003(); PageObject001 .Open(); P11_01.Login(TestDataMAP.get("ID").toString(), TestDataMAP.get("PW") .toString()); // ログイン状態の確認 Assertion_Condition.Auth_LogoutButtonAvailableCheck(); PageObject002.openP0003(); PageObject003.inputName(TestDataMAP.get("Name").toString()); PageObject003.inputName(TestDataMAP.get("TelNum").toString()); PageObject003.doSearch(); Assertion_TextElement .Assertion_ShowText_PerfectPatern(By.xpath("/html/body/div//table/tbody/tr/td/a"),TestDataMAP.get("Name").toString()); Assertion_TextElement .Assertion_ShowText_PerfectPatern(By.xpath("/html/body/div//table/tbody/tr/td/a"),TestDataMAP.get("TelNum").toString()); } }
・テストデータ用Yaml
1: ID: Jigsaw PW: Jigsawww Name: Jigsaw TelNum: 00-0000-0000