前回は、PlaywrightのセットアップとCodegenを使ったテストの記録方法を学びました。
今回は、より複雑なテストを作成するために、Playwrightの主要な機能と、そのコードの書き方について詳しく解説します。Yahoo! Japanを例に、具体的なコードを見ていきましょう。
※Googleを使って試そうとおもいましたが機械的なアクセスを検出してCAPTCHA認証が必要となるため今回は諦めました。CAPTCHA対応もあるらしいのでいつか記事にできれば。
ページオブジェクトモデル(POM)の実践
テストコードの可読性と保守性を高めるため、ページオブジェクトモデル(POM) を適用します。今回は、Yahoo! Japanのトップページと検索結果ページに対応するクラスを作成します。
Yahoo! Japanトップページのページオブジェクト
pages/YahooSearchPage.ts
import { type Page, type Locator } from '@playwright/test';
// Yahoo! Japan検索ページの要素と操作を管理するクラス
export class YahooSearchPage {
readonly page: Page;
readonly searchBox: Locator; // 型を明示
readonly searchButton: Locator; // 型を明示
constructor(page: Page) {
this.page = page; // pageプロパティを初期化
// ページプロパティが初期化された後、他の要素を定義
this.searchBox = this.page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' });
this.searchButton = this.page.getByRole('button', { name: '検索' });
}
// Yahoo! Japanトップページに移動するメソッド
async goto() {
await this.page.goto('https://www.yahoo.co.jp/');
}
// 検索キーワードを入力するメソッド
async searchFor(keyword: string) {
await this.searchBox.fill(keyword);
}
// 検索ボタンをクリックするメソッド
async clickSearchButton() {
await this.searchButton.click();
}
}
検索結果ページのページオブジェクト
pages/YahooResultsPage.ts
import { type Page, expect } from '@playwright/test';
// Yahoo! Japan検索結果ページの要素と操作を管理するクラス
export class YahooResultsPage {
readonly page: Page;
constructor(page: Page) {
this.page = page;
}
// 指定したキーワードが検索結果のタイトルに含まれることを検証するメソッド
async expectKeywordInTitle(keyword: string) {
// ページのタイトルにキーワードが含まれることを検証
await expect(this.page).toHaveTitle(new RegExp(keyword));
}
}
主なAPIとセレクター
Playwrightのテストを記述する上で、セレクターとアサーションは不可欠な要素です。
セレクター(要素の特定)
Playwrightは、HTML要素を特定するためのさまざまなセレクターを提供しています。
-
getByRole()
: 最も推奨されるセレクターです。アクセシビリティの役割(例:'searchbox'
,'button'
)に基づいて要素を特定します。// "検索"という名前のボタンを特定 page.getByRole('button', { name: '検索' });
-
getByText()
: 要素のテキストコンテンツに基づいて特定します。// "ヤフオク!"というテキストを含むリンクを特定 page.getByText('ヤフオク!');
-
getByLabel()
: ラベルのテキストに基づいてフォームコントロール(入力欄など)を特定します。// "検索したいキーワードを入力してください"というラベルを持つ入力欄を特定 page.getByLabel('検索したいキーワードを入力してください');
-
CSSセレクター: CSSセレクター(例:
id
,class
)を使用して要素を特定します。// IDが "yschsp" のフォームを特定 page.locator('#yschsp');
アサーション(検証)
テストが期待通りに動作したかを確認するために、アサーションを使用します。Playwrightはexpect
関数を提供しており、さまざまな検証が可能です。
-
toHaveTitle()
: ページのタイトルが特定の値と一致するかを検証します。await expect(page).toHaveTitle(/Playwright/);
-
toBeVisible()
: 要素が表示されているかを検証します。await expect(page.locator('#content')).toBeVisible();
-
toHaveURL()
: 現在のページのURLが特定の値と一致するかを検証します。await expect(page).toHaveURL(/search\.yahoo\.co\.jp/);
テストコードの作成と実行
次に、上記で作成したページオブジェクトを使って、テストコードを記述します。
tests/yahoo-search.spec.ts
import { test, expect } from '@playwright/test';
import { YahooSearchPage } from '../pages/YahooSearchPage';
import { YahooResultsPage } from '../pages/YahooResultsPage';
test('Yahoo! Japanでキーワードを検索すると、検索結果が表示される', async ({ page }) => {
// ページオブジェクトのインスタンスを作成
const yahooSearchPage = new YahooSearchPage(page);
const yahooResultsPage = new YahooResultsPage(page);
const keyword = 'Playwright とは';
// 1. Yahoo! Japanトップページに移動
await yahooSearchPage.goto();
// 2. 検索キーワードを入力
await yahooSearchPage.searchFor(keyword);
// 3. 検索ボタンをクリック
await yahooSearchPage.clickSearchButton();
// 4. 検索結果ページにキーワードが含まれることを検証
await yahooResultsPage.expectKeywordInTitle(keyword);
await expect(page).toHaveURL(/search\.yahoo\.co\.jp/); // URLが検索結果URLに変わったことを検証
});
コードの解説
-
ページオブジェクトモデル(POM): このアプローチでは、Yahoo! Japanの検索機能に関連するすべての要素と操作を、
YahooSearchPage
とYahooResultsPage
という専用のクラスにカプセル化しています。これにより、UIのセレクターが変更されても、テストコード自体を修正する必要がなくなり、テストの保守性が大幅に向上します。 -
セマンティックセレクター:
page.getByRole('searchbox', { ... })
のように、HTML要素の役割とアクセシビリティに基づいて要素を特定しています。この方法は、IDやクラス名に依存するCSSセレクターよりも堅牢で、UIの見た目が変わってもテストが壊れにくいという利点があります。 -
アサーション:
expect()
関数を使用して、ページのタイトルやURL、要素の可視性といった検証を行っています。これらはテストが期待通りに動作したかを確認するために不可欠です。Playwrightは、要素が表示されるまで自動待機するため、多くの場合は明示的な待機コードは不要です。
これらの機能を使いこなすことで、信頼性の高い、メンテナンスしやすいテストコードを効率的に記述できるようになります。
実行結果
このテストを実行すると、testsフォルダの親フォルダにplaywright-report
フォルダが作成されレポートHTMLが作成されます。
レポートHTMLは以下のように作成されるのでぜひ確認してみてください。