ページオブジェクトモデル(POM)とページファクトリ

1. 概要

テストコードの可読性・再利用性・保守性を高めるため、Selenium では

  1. ページオブジェクトモデル(POM) – 画面要素とその操作を 1 クラスに集約するデザインパターン

  2. ページファクトリ(PageFactory) – POM クラスの WebElement を遅延ロード(Lazy-Load)するユーティリティ
    の 2 段構えでテスト設計を行うことが推奨されています。browserstack.com


2. ページオブジェクトモデル(POM)

目的 詳細
疎結合 テストスクリプトと UI 構造を分離し、UI 変更時の影響範囲を最小化する
一元管理 同じ画面操作を 1 ヵ所(※ページクラス)にまとめ、重複コードを排除する
ビジネス用語で記述 低レベルのセレクタではなく、login()addToCart() といったドメイン用語でメソッドを公開

典型的な構造(Java 例)

java
public class LoginPage { private final WebDriver driver; private final By userField = By.id("user"); private final By passField = By.id("pass"); private final By submitBtn = By.id("login"); public LoginPage(WebDriver driver){ this.driver = driver; } public void loginAs(String u, String p){ driver.findElement(userField).sendKeys(u); driver.findElement(passField).sendKeys(p); driver.findElement(submitBtn).click(); } }

3. ページファクトリ(PageFactory)

PageFactory は フィールドアノテーション + 遅延プロキシにより、

  • 要素取得ロジックの重複をさらに削減

  • 初回アクセス時にだけ findElement することで DOM 変化への耐性を確保
    を実現するヘルパです。Java では PageFactory.initElements() が入口になります。selenium.dev

アノテーション利用例(Java)

java
public class LoginPage { @FindBy(id = "user") private WebElement userField; @FindBy(id = "pass") private WebElement passField; @FindBy(id = "login") private WebElement submitBtn; public LoginPage(WebDriver driver){ PageFactory.initElements(driver, this); } public void loginAs(String u, String p){ userField.sendKeys(u); passField.sendKeys(p); submitBtn.click(); } }

主なアノテーション

アノテーション 説明
@FindBy CSS, XPath, id など多彩な定位方法を指定
@FindBys / @FindAll 複合条件(AND/OR)検索
@CacheLookup 1 度取得した要素をキャッシュ(DOM が動的に変わらない画面向き)

4. POM + PageFactory の保守メリット

  1. UI レイヤ変更時の影響範囲がページクラス内に閉じる

  2. テストコードはビジネスフローのみを記述 – DSL (Domain-Specific Language) 風で読みやすい

  3. 遅延ロードでタイミング依存を低減(Ajax 画面でも安定しやすい)testgrid.io


5. Selenium 4 以降の注意点

言語バインディング 状況 対策
Java / Python PageFactory は 引き続き公式 selenium-support に含まれる そのまま使用可 frugaltesting.com
.NET Selenium 4 から PageFactory.InitElements が core パッケージに無くなり、DotNetSeleniumExtras.PageObjects 外部ライブラリへ NuGet で Extras を追加し PageFactory.InitElements(driver, this) を呼び出す stackoverflow.com

推奨

  • 新規プロジェクト: コンストラクタ注入 + By 定義方式(PageFactory 依存ゼロ)も選択肢

  • 既存資産が多い場合: PageFactory を維持しつつ段階的にリファクタリング


6. ベストプラクティスまとめ

チェックリスト 説明
単一責任 1 ページ=1 クラス、共通ヘッダーやモーダルは再利用用クラス化
読みやすいメソッド名 clickLoginButton() より loginAs() のような業務動詞+目的語
待機戦略を隠蔽 ページクラス内に waitForPageLoaded() を実装しテスト側を簡潔に
テストデータ管理 データ駆動 (CSV/JSON) を導入し、ページクラスでは値を受け取るだけに
継続的レビュー UI 改修時にはページクラス → スモークテスト → 回帰テストの順で更新

POM と PageFactory を適切に組み合わせれば、UI 変更が頻繁な Web アプリでも 「壊れにくいテストスイート」 を構築できます。

ChatGPT4o 生成日:2025/06/21