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