ベストプラクティス
はじめに
このガイドは、Playwrightのベストプラクティスに従い、より堅牢なテストを記述するのに役立ちます。
テストの哲学
ユーザーが目にする動作をテストする
自動テストは、アプリケーションコードがエンドユーザーに対して機能することを検証し、ユーザーが通常使用しない、見ない、あるいは関知しないであろう実装の詳細(関数の名前、配列であるかどうか、ある要素のCSSクラスなど)に依存するのを避けるべきです。エンドユーザーはページにレンダリングされたものを見たり操作したりするため、テストも通常、同じレンダリングされた出力のみを見たり操作したりするべきです。
テストを可能な限り分離する
各テストは他のテストから完全に分離され、独自のローカルストレージ、セッションストレージ、データ、クッキーなどを用いて独立して実行されるべきです。テストの分離は再現性を向上させ、デバッグを容易にし、連鎖的なテスト失敗を防ぎます。
テストの特定の部分での繰り返しを避けるために、beforeおよびafterフックを使用できます。テストファイル内にbeforeフックを追加して、各テストの前にテストの一部を実行します。たとえば、特定のURLにアクセスしたり、アプリの一部にログインしたりします。これにより、テストが相互に依存しないため、テストが分離されます。ただし、テストが十分に単純な場合は、特にテストをより明確で読みやすく、保守しやすくするために、多少の重複があっても問題ありません。
import { test } from '@playwright/test';
test.beforeEach(async ({ page }) => {
// Runs before each test and signs in each page.
await page.goto('https://github.com/login');
await page.getByLabel('Username or email address').fill('username');
await page.getByLabel('Password').fill('password');
await page.getByRole('button', { name: 'Sign in' }).click();
});
test('first', async ({ page }) => {
// page is signed in.
});
test('second', async ({ page }) => {
// page is signed in.
});
セットアッププロジェクトを使用すると、テストでサインイン状態を再利用することもできます。そうすれば、一度ログインするだけで、すべてのテストでログインステップをスキップできます。
サードパーティの依存関係のテストを避ける
自分で管理しているものだけをテストしてください。管理していない外部サイトやサードパーティサーバーへのリンクをテストしようとしないでください。これらは時間がかかり、テストを遅くするだけでなく、リンク先のページの内容を制御したり、クッキーバナーやオーバーレイページ、その他のテスト失敗の原因となるものを制御したりすることができません。
代わりに、Playwright Network API を使用して、必要なレスポンスを保証してください。
await page.route('**/api/fetch_data_third_party_dependency', route => route.fulfill({
status: 200,
body: testData,
}));
await page.goto('https://example.com');
データベースを使ったテスト
データベースを扱う場合は、データを管理していることを確認してください。ステージング環境でテストを行い、それが変更されないように確認してください。ビジュアルリグレッションテストの場合、オペレーティングシステムとブラウザのバージョンが同じであることを確認してください。
ベストプラクティス
ロケーターを使用する
エンドツーエンドテストを書くためには、まずウェブページ上の要素を見つける必要があります。これは、Playwrightに組み込まれているロケーターを使用することで実現できます。ロケーターには自動待機とリトライ機能が備わっています。自動待機とは、Playwrightがクリックを実行する前に、要素が可視で有効であることなど、要素に対してさまざまな操作性チェックを実行することを意味します。堅牢なテストを作成するために、ユーザーが目にする属性と明示的なコントラクトを優先することをお勧めします。
// 👍
page.getByRole('button', { name: 'submit' });
チェインとフィルタリングを使用する
ロケーターは、ページの特定の部分に検索を絞り込むためにチェインすることができます。
const product = page.getByRole('listitem').filter({ hasText: 'Product 2' });
また、ロケーターをテキストまたは別のロケーターでフィルタリングすることもできます。
await page
.getByRole('listitem')
.filter({ hasText: 'Product 2' })
.getByRole('button', { name: 'Add to cart' })
.click();
XPathやCSSセレクターよりもユーザーが目にする属性を優先する
DOMは簡単に変更される可能性があるため、テストがDOM構造に依存すると、テストが失敗する原因となる可能性があります。たとえば、CSSクラスでこのボタンを選択することを考えてみてください。デザイナーが何かを変更すると、クラスが変更され、テストが壊れる可能性があります。
// 👎
page.locator('button.buttonIcon.episode-actions-later');
DOMの変更に強いロケーターを使用してください。
// 👍
page.getByRole('button', { name: 'submit' });
ロケーターを生成する
Playwrightには、テストを生成し、ロケーターを自動で選択できるテストジェネレーターがあります。ページを分析し、役割、テキスト、テストIDのロケーターを優先して最適なロケーターを特定します。ジェネレーターがロケーターに一致する複数の要素を見つけた場合、そのロケーターを堅牢にし、ターゲット要素を一意に識別するように改善するため、ロケーターが原因でテストが失敗することを心配する必要はありません。
codegen
を使用してロケーターを生成する
ロケーターを選択するには、`codegen` コマンドの後にロケーターを選択したいURLを続けて実行します。
- npm
- yarn
- pnpm
npx playwright codegen playwright.dev
yarn playwright codegen playwright.dev
pnpm exec playwright codegen playwright.dev
これにより、新しいブラウザウィンドウとPlaywrightインスペクターが開きます。ロケーターを選択するには、まず「レコード」ボタンをクリックして記録を停止します。デフォルトでは、`codegen` コマンドを実行すると、新しい記録が開始されます。記録を停止すると、「ロケーターを選択」ボタンがクリックできるようになります。
ブラウザウィンドウでページの任意の要素にカーソルを合わせると、カーソルの下にロケーターがハイライト表示されます。要素をクリックすると、ロケーターがPlaywrightインスペクターに追加されます。ロケーターをコピーしてテストファイルに貼り付けることも、Playwrightインスペクターで編集することでロケーターをさらに探求することもできます。たとえば、テキストを変更してブラウザウィンドウで結果を確認できます。

VS Code拡張機能を使用してロケーターを生成する
VS Code拡張機能を使って、ロケーターの生成やテストの記録を行うこともできます。VS Code拡張機能は、テストの記述、実行、デバッグの際にも優れた開発者エクスペリエンスを提供します。

Webファーストのアサーションを使用する
アサーションは、期待される結果と実際の結果が一致するかどうかを検証する方法です。Webファーストのアサーションを使用すると、Playwrightは期待される条件が満たされるまで待機します。たとえば、アラートメッセージをテストする場合、テストはメッセージを表示させるボタンをクリックし、アラートメッセージが存在することを確認します。アラートメッセージが表示されるのに0.5秒かかる場合、`toBeVisible()`のようなアサーションは必要に応じて待機し、リトライします。
// 👍
await expect(page.getByText('welcome')).toBeVisible();
// 👎
expect(await page.getByText('welcome').isVisible()).toBe(true);
手動のアサーションを使用しない
期待値を待機しない手動のアサーションは使用しないでください。以下のコードでは、awaitがexpectの前にではなく内部にあります。`isVisible()`のようなアサーションを使用する場合、テストは1秒も待たずに、ロケーターが存在することを確認してすぐに返します。
// 👎
expect(await page.getByText('welcome').isVisible()).toBe(true);
代わりに、`toBeVisible()` のようなWebファーストのアサーションを使用してください。
// 👍
await expect(page.getByText('welcome')).toBeVisible();
デバッグを設定する
ローカルデバッグ
ローカルでのデバッグには、VS Code拡張機能をインストールしてVS Codeでテストをライブデバッグすることをお勧めします。実行したいテストの行の隣で右クリックすると、テストをデバッグモードで実行でき、ブラウザウィンドウが開き、ブレークポイントが設定されている場所で一時停止します。

VS Codeでテスト内のロケーターをクリックまたは編集することで、テストをライブデバッグできます。これにより、ブラウザウィンドウでこのロケーターがハイライト表示され、ページ上で見つかった他の一致するロケーターも表示されます。

Playwrightインスペクターでテストをデバッグするには、`--debug` フラグを付けてテストを実行します。
- npm
- yarn
- pnpm
npx playwright test --debug
yarn playwright test --debug
pnpm exec playwright test --debug
その後、テストをステップ実行し、操作性のログを表示し、ロケーターをライブで編集してブラウザウィンドウでハイライト表示されるのを確認できます。これにより、どのロケーターが一致し、それがいくつあるかが表示されます。

特定のテストをデバッグするには、テストファイルの名前とテストの行番号の後に `--debug` フラグを追加します。
- npm
- yarn
- pnpm
npx playwright test example.spec.ts:9 --debug
yarn playwright test example.spec.ts:9 --debug
pnpm exec playwright test example.spec.ts:9 --debug
CIでのデバッグ
CIでの失敗の場合、動画やスクリーンショットの代わりにPlaywrightのトレースビューアーを使用してください。トレースビューアーは、テストの完全なトレースをローカルのプログレッシブウェブアプリ(PWA)として提供し、簡単に共有できます。トレースビューアーを使用すると、タイムラインの表示、開発ツールを使用した各アクションのDOMスナップショットの検査、ネットワークリクエストの表示などを行うことができます。

トレースはPlaywright設定ファイルで設定され、失敗したテストの最初のリトライ時にCIで実行されるように設定されています。パフォーマンスに大きな影響を与えるため、すべてのテストでトレースが実行されるように `on` に設定することはお勧めしません。ただし、開発中に `--trace` フラグを使用してローカルでトレースを実行することは可能です。
- npm
- yarn
- pnpm
npx playwright test --trace on
yarn playwright test --trace on
pnpm exec playwright test --trace on
このコマンドを実行すると、各テストのトレースが記録され、HTMLレポートから直接確認できます。
- npm
- yarn
- pnpm
npx playwright show-report
yarn playwright show-report
pnpm exec playwright show-report

トレースは、テストファイル名の隣にあるアイコンをクリックするか、各テストレポートを開いてトレースセクションまでスクロールすることで開くことができます。

Playwrightのツールを使用する
Playwrightには、テスト作成を支援するさまざまなツールが付属しています。
- VS Code拡張機能は、テストの記述、実行、デバッグにおいて優れた開発者エクスペリエンスを提供します。
- テストジェネレーターは、テストを生成し、ロケーターを自動で選択してくれます。
- トレースビューアーは、テストの完全なトレースをローカルPWAとして提供し、簡単に共有できます。トレースビューアーを使用すると、タイムラインの表示、各アクションのDOMスナップショットの検査、ネットワークリクエストの表示などが可能です。
- UIモードでは、タイムトラベル体験とウォッチモードを備え、テストの探索、実行、デバッグが可能です。すべてのテストファイルはテストサイドバーにロードされ、各ファイルとdescribeブロックを展開して、個々のテストを個別に実行、表示、監視、デバッグできます。
- PlaywrightのTypeScriptは、すぐに利用でき、より優れたIDE統合を提供します。IDEは、実行できるすべてのことを表示し、誤りがある場合には強調表示します。TypeScriptの経験は必要なく、コードがTypeScriptである必要もありません。必要なのは、`.ts` 拡張子でテストを作成することだけです。
すべてのブラウザでテストする
Playwrightを使えば、プラットフォームに関係なく、すべてのブラウザでサイトを簡単にテストできます。すべてのブラウザでテストすることで、アプリがすべてのユーザーに機能することを保証します。設定ファイルで、名前と使用するブラウザまたはデバイスを追加してプロジェクトを設定できます。
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
});
Playwrightの依存関係を最新に保つ
Playwrightのバージョンを最新の状態に保つことで、最新のブラウザバージョンでアプリをテストし、最新のブラウザバージョンが一般公開される前に失敗をキャッチすることができます。
- npm
- yarn
- pnpm
npm install -D @playwright/test@latest
yarn add --dev @playwright/test@latest
pnpm install --save-dev @playwright/test@latest
リリースノートをチェックして、最新バージョンとリリースされた変更点を確認してください。
次のコマンドを実行すると、Playwrightのバージョンを確認できます。
- npm
- yarn
- pnpm
npx playwright --version
yarn playwright --version
pnpm exec playwright --version
CIでテストを実行する
CI/CDをセットアップし、頻繁にテストを実行してください。テストを実行する頻度が高いほど良いです。理想的には、各コミットとプルリクエストでテストを実行するべきです。PlaywrightにはGitHub Actionsワークフローが付属しており、セットアップ不要でCIでテストを実行できます。Playwrightは、選択したCI環境でも設定できます。
CIでテストを実行する場合は、コストが安いためLinuxを使用してください。開発者はローカルで実行する際にどのような環境でも使用できますが、CIではLinuxを使用してください。シャーディングを設定してCIを高速化することを検討してください。
CIでのブラウザダウンロードを最適化する
特にCIでは、実際に必要なブラウザだけをインストールしてください。たとえば、Chromiumのみでテストしている場合は、Chromiumだけをインストールします。
# Instead of installing all browsers
npx playwright install --with-deps
# Install only Chromium
npx playwright install chromium --with-deps
これにより、CIマシンのダウンロード時間とディスクスペースの両方を節約できます。
テストをLintする
エラーを早期に検出するために、TypeScriptとESLintによるlintingをテストに推奨します。`@typescript-eslint/no-floating-promises` ESLint ルールを使用して、Playwright APIへの非同期呼び出しの前に await の欠落がないことを確認してください。CIでは `tsc --noEmit` を実行して、関数が正しいシグネチャで呼び出されていることを確認できます。
並列処理とシャーディングを使用する
Playwrightはデフォルトでテストを並列で実行します。単一ファイル内のテストは、同じワーカープロセスで順序通りに実行されます。単一ファイル内に多くの独立したテストがある場合、それらを並列で実行したい場合があります。
import { test } from '@playwright/test';
test.describe.configure({ mode: 'parallel' });
test('runs in parallel 1', async ({ page }) => { /* ... */ });
test('runs in parallel 2', async ({ page }) => { /* ... */ });
Playwrightはテストスイートをシャード分割し、複数のマシンで実行することができます。
- npm
- yarn
- pnpm
npx playwright test --shard=1/3
yarn playwright test --shard=1/3
pnpm exec playwright test --shard=1/3
生産性向上チップス
ソフトアサーションを使用する
テストが失敗した場合、Playwrightはテストのどの部分が失敗したかを示すエラーメッセージをVS Code、ターミナル、HTMLレポート、またはトレースビューアーで表示します。しかし、ソフトアサーションを使用することもできます。これらはテストの実行をすぐに終了させず、テストが終了した後に失敗したアサーションのリストをコンパイルして表示します。
// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success');
// ... and continue the test to check more things.
await page.getByRole('link', { name: 'next page' }).click();