CSS/XPathセレクターの使用

Playwright における CSS/XPath セレクターの基本

観点 CSS セレクター XPath セレクター
書式例 button.submit / #login-form input[name="email"] //button[@class="submit"] / //*[@id="login-form"]//input[@name="email"]
機能 ブラウザ標準のセレクター API をそのまま利用。柔軟かつ高速で、疑似クラス :nth-child や属性・部分一致なども使用可能 DOM 階層をパス形式で記述。先祖/兄弟要素など構造を重視した検索が得意。任意軸や条件付きノードテストが可能
Playwright での指定方法 省略可(デフォルトで CSS と解釈)
page.locator("button.submit")
"xpath=" プレフィックス必須
page.locator("xpath=//button[@class='submit']")
推奨度 : 可読性が高く、公式も CSS を第一候補に推奨 特殊ケースのみ: 階層・位置関係でしか表現できない条件がある場合に限定

1. Playwright の “Locator” と自動待機

Playwright のすべての操作は Locator オブジェクト を介して行います。
page.locator(selector) が返す Locator は、操作直前まで要素を解決しない lazy evaluation 方式です。
以下 3 点の“自動待機(auto-waiting)”がデフォルトで組み込まれているため、通常は明示的に waitFor* を呼び出す必要はありません。

  1. 要素の出現: DOM に存在し表示されるまで待機

  2. 要素のアクション可能状態: click() ならヒットボックスが必ず視野内かつ無効化されていない

  3. ページの安定化: 連続リクエスト後にネットワークがアイドル状態になるまで

ts
await page.locator('button.submit').click(); // 出現+可視+クリック可能になるまで自動待機

2. CSS セレクターの詳細

a. 基本構文

ts
await page.locator('#cart .item[data-id="42"]'); await page.locator('form >> text="送信"'); // テキスト一致 await page.locator('button:has-text("次へ")'); // 疑似セレクター :has-text
  • チェーン演算子 >>
    複数の部分セレクターを段階的に絞り込む。前段の結果を限定スコープとして次段を検索。
    例: 'header >> nav >> a.active'

  • Playwright 拡張疑似クラス

    拡張 用途
    :visible レンダリング上表示されているノードのみ
    :has() CSS4 相当の後続ノード条件
    :has-text("...") 子孫テキストを部分一致検索
    :nth-match(expr, n) セレクター expr の n 番目

b. 正規表現による一致

ts
await page.locator('text=/ログイン\\s*成功/');

CSS ではなく text エンジン に切り替わるが、Locator と組み合わせて待機/操作が可能。


3. XPath セレクターの詳細

XPath は以下のように DOM 階層を明示 できるため、兄弟・先祖関係を厳密に指定したい場合に有用です。

ts
await page.locator('xpath=//*[@role="dialog"]//button[normalize-space()="閉じる"]');
  • normalize-space() で前後空白を除去

  • 任意軸 preceding-sibling::, ancestor:: なども利用可

  • ただし 可読性・保守性が下がりやすい ため常用は避けるのがベストプラクティス


4. 明示的な待機が必要になるケース

説明 解決策
動的クラス変更で DOM ノード自体は変わらない class 属性だけ切替わる SPA await locator.waitFor({ state: 'visible' })
JS で display:none → block が遅延 スタイル変化完了まで待機 await locator.waitFor({ state: 'attached' })toBeVisible()
非同期処理完了後に属性が追加 data-ready="true" が付くまで await expect(locator).toHaveAttribute('data-ready', 'true');

Playwright には expect ライブラリ が組み込まれており、Assertion 自体が暗黙に待機を伴います。

ts
import { expect } from '@playwright/test'; await expect(page.locator('img#avatar')).toBeVisible();

5. ベストプラクティス

  1. First-class locators を優先
    getByRole(), getByTestId(), getByLabel() はアクセシビリティ対応かつ変更に強い。

  2. CSS をデフォルトに
    サイト構造が多少変わっても属性単位で耐性が高い。data-testid 属性を専用に用意すると保守が楽。

  3. ネスト深度を浅く保つ
    header >> nav >> a.active のように コンポーネント単位で範囲を限定 してから子要素を選ぶとセレクターの変更影響を局所化できる。

  4. XPath 乱用を避ける
    どうしても兄弟順序や複雑な先祖条件が必要なときのみ使用。テスト失敗時の可読性にも影響。

  5. 待機の二重掛けに注意
    page.waitForSelector() の後に同じ Locator で click() を呼ぶと、二重待機で不要な遅延が発生する。


6. 具体例:ログインフォームの自動テスト

ts
import { test, expect } from '@playwright/test'; test('ログイン処理', async ({ page }) => { await page.goto('https://example.com/login'); const email = page.locator('input[name="email"]'); const password = page.locator('input[name="password"]'); const submit = page.locator('button:has-text("ログイン")'); await email.fill('user@example.com'); await password.fill('secret'); await submit.click(); // 自動待機でリダイレクト完了を検知 await expect(page).toHaveURL(/\/dashboard/); // XPath でアバター画像を確認(class の有無が変わる場合) const avatar = page.locator('xpath=//*[@id="sidebar"]//img[contains(@class,"avatar")]'); await expect(avatar).toBeVisible(); });

まとめ

  • Playwright は Locator API自動待機 により、セレクター指定だけで多くの待機処理を吸収できます。

  • CSS セレクター を第一候補とし、アクセシビリティ属性や data-testid を併用すると堅牢なテストが書けます。

  • XPath は階層が重要なとき限定で使用。複雑になるほど保守負荷が高まるため乱用しない。

  • 明示的な waitFor* は「DOM はあるが状態だけ変わる」ケースに絞り、通常は Expect API の暗黙待機を活用する。

これらの原則を踏まえて、セレクター設計と待機戦略を最適化することで、テスト実行の安定性と速度を両立できます。

ChatGPT4o 生成日:2025/06/22