Playwrightの公式ドキュメントに「Best Practices」というページがあったので翻訳してみました。
原文: Best Practices | 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.
});
また、サインインした状態をプロジェクトの初期セットアップによって再利用することもできます。そうすれば、一度だけログインすれば、すべてのテストでログインステップを省略することができます。
訳注: ログイン処理などは、毎回アカウント作成して、毎回ログインしたほうが独立性が保てるかなと思ったけど、Basic: shared account in all testsではアカウントの共有を推奨していますね。共有によって楽にはなるけど、あるテストの操作が他に影響でないように考慮して作らないと、テストの並列実行数を増やせなくなりそうです。
サードパーティの依存関係をテストしない
自分が管理しているものだけをテストしましょう。自分が管理していない外部サイトやサードパーティのサーバーへのリンクをテストしようとしないでください。テストに時間がかかり、遅くなるだけでなく、リンク先のページ、クッキーバナーやオーバーレイページなど、テストが失敗する可能性のあるものを制御できません。
代わりに、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 Network APIはAPI等の Mocking などができる機能。テスト範囲を絞り込むために、外部など管理外の領域を Mock 化していくのは E2E でも必要。
データベースを使ったテスト
データベースを使用する場合は、データを管理しましょう。ステージング環境でテストを行い、データが変わっていないことを確認します。視覚的なリグレッション・テストでは、オペレーティング・システムとブラウザのバージョンが同じであることを確認してください。
訳注: 原文「If working with a database then make sure you control the data. Test against a staging environment and make sure it doesn’t change.」。データに影響しないようにデータを管理しましょうということかな?
ベストプラクティス
ロケータを使う
エンド・ツー・エンドのテストを書くためには、まずウェブページ上の要素を見つける必要があります。これを行うには、 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を続けて実行します。
npx playwright codegen playwright.dev
codegen
コマンドを叩くと、新しいブラウザウィンドウと Playwright インスペクタが開きます。最初のロケーターを選ぶには、「Record」ボタンをクリックして録画を停止します。デフォルトでは、 codegen
コマンドを実行すると新しい記録が開始されます。録音を停止すると、「Pick Locator」ボタンがクリックできるようになります。
ブラウザウィンドウでページ上の任意の要素にカーソルを合わせると、カーソルの下にロケーターがハイライト表示されます。要素をクリックすると、ロケータが Playwright インスペクタに追加されます。ロケータをコピーしてテストファイルに貼り付けたり、 Playwright インスペクタ上のテキストを修正するなどしてロケータを編集し、ブラウザウィンドウで結果を見ながら探索を続けられます。
VS Code 拡張機能を使用してロケーターを生成する
VS Codeエクステンションを使用して、ロケーターを生成したり、テストを記録することもできます。また、VS Code 拡張機能を使用すると、テストの記述、実行、およびデバッグを行う際に、優れた開発者体験を得られます。
ウェブファーストのアサーションを使う
アサーションは、期待される結果と実際の結果が一致するかどうかを検証する方法です。ウェブファーストアサーションを使用すると、 Playwright は期待する条件が満たされるまで待機します。例えば、アラートメッセージをテストする場合、テストはメッセージを表示させるボタンをクリックし、アラートメッセージがあるかどうかをチェックすると思います。アラートメッセージが表示されるまでに 0.5 秒かかる場合、必要があれば要素の出現を待ったり、リトライを仕掛けたりする toBeVisible(
) のようなアサーションを使用します。
// 👍
await expect(page.getByText('welcome')).toBeVisible();
// 👎
expect(await page.getByText('welcome').isVisible()).toBe(true);
手動でアサーションを使わない
予期している要素の存在を待ってくれない手動アサーションを使わないでください。以下のコードを見てみると、await
は expect
ファンクションの前ではなく中にあります。こうしてしまうと、isVisible()
のようなアサーションを使用する場合、テストは一秒たりとも待たなくなります。ロケーターの存在をすぐに確認し、すぐに結果を返してしまうからです。
// 👎expect(await page.getByText('welcome').isVisible()).toBe(true);
代わりにtoBeVisible()のようなウェブファーストのアサーションを使います。
// 👍await expect(page.getByText('welcome')).toBeVisible();
デバッグの設定
ローカル環境でデバッグする
ローカルデバッグを行うなら、 VS Code 拡張モジュールをインストールして、 VS Code でテストをデバッグすることをお勧めします。実行したいテストの横の行を右クリックすれば、デバッグモードでテスト実行が可能になり、ブラウザウィンドウを開き、ブレークポイントが設定された位置で一時停止します。
VS Code でテスト内のロケータをクリックまたは編集することで、テストをライブデバッグできます。対象のロケータはブラウザウィンドウでハイライトされ、ページ上で見つかった他の一致するロケータも表示されます。
また、 --debug
フラグを付けてテストを実行すると、Playwright インスペクタ上でテストをデバッグできます。
npx playwright test --debug
テストを実行し、アクショナビリティログを表示し、実行しながらロケータを編集し、ブラウザウィンドウでハイライト表示できます。これにより、どのロケータがマッチするか、いくつマッチするかがわかります。
訳注:アクショナビリティログは、Playwright インスペクタで確認できる実行ログ
特定のテストをデバッグする場合は、テストファイル名とテストの行番号の後に–debugフラグを付けます。
npx playwright test example.spec.ts:9 --debug
CIでのデバッグ
CIで失敗した場合は、動画やスクリーンショットの代わりに Playwright のトレースビューアを使用できます。トレースビューアでは、テストの完全なトレースをローカルの Progressive Web App (PWA) として簡単に共有できます。トレースビューアを使用すると、実行したテストのタイムラインを表示したり、開発ツールを使用して各アクションの DOM スナップショットを検査したり、ネットワークリクエストを表示したりできます。
トレースビューアは Playwright 設定ファイルで設定され、失敗したテストの最初の再試行時に CI で実行されるように設定されます。すべてのテストでトレースが実行されるようにon
と設定することは、パフォーマンスが非常に重くなるためお勧めしません。しかし、--trace
フラグを指定しながら開発するのであれば、ローカルでトレースを実行しても問題にならないはずです。
npx playwright test --trace on
このコマンドを実行すると、各テストのトレースが記録され、HTML レポートから直接見ることができます。
npx playwright test --trace on --reporter=html
npx playwright show-report
トレースは、テストの横にあるアイコンをクリックするか、各テストレポートを開いてトレースセクションまでスクロールすれば開けます。
Playwrightのツールを使う
Playwright には、テスト作成に役立つさまざまなツールが用意されています。
- VS Code 拡張は、テストの記述、実行、デバッグの際に優れた開発者体験を提供します。
- テストジェネレータは、テストを生成したり、ロケータをピックアップしてくれます。
- トレースビューアは、ローカル PWA としてテストの完全なトレースを提供し、簡単に共有できます。トレースビューアでは、タイムラインの表示、各アクションの DOM スナップショットの検査、ネットワークリクエストの表示などが可能です。
- UIモードでは、画面をウォッチしながらテスト実行されるので、タイムトラベルのような体験を通してテストを探索、実行、デバッグできます。すべてのテストファイルは testing サイドバーにロードされるため、各ファイルを画面上に展開したり、個別に記述ブロックを描写でき、各テストを実行、表示、監視、デバッグできます。
- Playwright を TypeScript で実装すれば、すぐに動作し、優れた IDE との統合が可能です。IDEはあなたができることをすべて表示し、何か間違ったことをするとハイライトします。TypeScript の経験は必要ありません。コードが TypeScript である必要もありません。必要なのは拡張子
.ts
でテストを作成するだけです。
すべてのブラウザでテスト
Playwright では、プラットフォームを問わず、すべてのブラウザを使って簡単にテストできます。すべてのブラウザでテストすれば、すべてのユーザーの環境でアプリが動作することを保証できます。テストするブラウザの設定は、設定ファイルにプロジェクトの名前と使用するブラウザ、またはデバイスを追加して設定できます。
// playwright.config.ts
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 install -D @playwright/test@latest
リリースノートをチェックして、最新バージョンとリリースされた変更点を確認します。
npx playwright --version
CIでテストを実行する
CI/CD をセットアップし、テストを頻繁に実行しましょう。テストの実行頻度は多ければ多いほど良いです。コミットやプルリクエストのたびにテストを実行するのが理想的です。Playwright にはGitHubアクションのワークフローが付属しており、GitHubを利用するのであれば、設定不要でCI上でテストを実行できます。もちろん、Playwright をお好みのCI環境でセットアップもできます。
CI 上でテストを実行するときは、Linux を使ったほうが安上がりです。開発者は、ローカルでテスト実行するときはどんな環境でいいですが、CI上ではLinuxを使いましょう。
Lintを利用する
Lint を利用することで、エラーを早期に発見できます。@typescript-eslint/no-floating-promises
の ESLint ルールを使って、Playwright API の非同期呼び出しの前にawaitがないことを確認できます。
並列処理とシャーディングの使用
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 はテストスイートをシャードして、複数のマシンで実行できます。
npx 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();
*
このベストプラクティスはPlaywrightに特化型のベストプラクティスだけど、E2E全体的なベストプラクティスを知りたい方は「E2Eテスト自動化を成功に導く10のベストプラクティス」も参考にどうぞ。
追記: Cypressのベストプラクティスも翻訳してみました。
[…] […]
いいねいいね
[…] Playwrightのベストプラクティスを翻訳してみた […]
いいねいいね