paint-brush
Heroku での Playwright と Chrome ブラウザのテスト: 初心者向けガイド@alvinslee
新しい歴史

Heroku での Playwright と Chrome ブラウザのテスト: 初心者向けガイド

Alvin Lee12m2024/12/03
Read on Terminal Reader

長すぎる; 読むには

このブログでは、Heroku 上の Headless Chrome を使用して、React アプリの自動化されたエンドツーエンドの Playwright テストを実行する方法を説明します。
featured image - Heroku での Playwright と Chrome ブラウザのテスト: 初心者向けガイド
Alvin Lee HackerNoon profile picture

私はいつも、ユニット テストが実行される (そして合格する) のを見るのが大好きでした。ユニット テストは高速で、テストに合格すると、個々の部分が想定どおりに動作するという確信が得られます。逆に、ブラウザーのエンドツーエンド テストの作成と実行に非常に時間がかかるため、その優先順位付けに苦労することがよくありました。


幸いなことに、エンドツーエンドのブラウザ内テスト用のツールは、ここ数年で大幅に改善され、高速化しています。また、ヘッドレス ブラウザのセットアップにより、ブラウザ テストを CI の一部として実行できます。


最近、Heroku CI 内でヘッドレス Chrome を使用してブラウザ内テストを自動化する方法について説明しているHeroku ブログ投稿を見つけました。Heroku にはヘッドレス Chrome をインストールするビルドパックがあり、CI パイプラインでテストに呼び出すことができます。


ブログ投稿のサンプル設定は、 PuppeteerJestでテストされた React アプリでした。これは素晴らしいスタートですが、Puppeteer の代わりにPlaywright を使用したらどうなるでしょうか? それは可能ですか?


調べてみることにしました。結局のところ、Playwright でも同じことができるのです! そこで、Heroku CI で使用されるヘッドレス Chrome ブラウザで Playwright テストを実行するために必要な手順をまとめました。この記事では、セットアップの手順を説明します。

エンドツーエンドテストのためのブラウザ自動化について

エンドツーエンドのテストでは、ユーザーがブラウザで実際にアプリを操作する方法をキャプチャし、完全なワークフローを検証します。Playwright では、Chrome、Firefox、Safari でのテストにより、このプロセスを非常にシームレスに実行できます。もちろん、CI でブラウザ テストのフル スレートを実行するのはかなり負荷がかかるため、ヘッドレス モードが役立ちます。


Heroku のChrome for Testing ビルドパックは、Heroku アプリに Chrome をインストールするので、非常に軽量なセットアップで Heroku CI で Playwright テストを実行できます。

テスト申請の概要

ちょうど試してみたかったので、Heroku ブログ投稿で最初に参照された GitHub リポジトリをフォークしました。アプリケーションは、リンク、テキスト入力、送信ボタンを備えたシンプルな React アプリでした。テストは 3 つありました。


  1. リンクが機能し、正しい場所にリダイレクトされることを確認します。
  2. テキスト入力にユーザー入力が正しく表示されることを確認します。
  3. フォームを送信すると、ページに表示されるテキストが更新されることを確認します。


とても簡単です。あとは、Puppeteer と Jest の代わりに Playwright を使用するようにコードを変更するだけです。あ、npm の代わりにpnpmも使いたいと思いました。こちらがフォークした GitHub リポジトリへのリンクです。

Playwrightを使用するためにコードを変更する

コードを変更するために私が実行した手順を見ていきましょう。私はheroku-examplesリポジトリと同一のフォークされたリポジトリから始めました。

pnpmを使用する

私は npm ではなく pnpm を使いたかったのです。(個人的な好みです。) そこで、まず次の操作を実行しました。

 ~/project$ corepack enable pnpm ~/project$ corepack use pnpm@latest Installing [email protected] in the project… … Progress: resolved 1444, reused 1441, downloaded 2, added 1444, done … Done in 14.4s ~/project$ rm package-lock.json ~/project$ pnpm install # just to show everything's good Lockfile is up to date, resolution step is skipped Already up to date Done in 1.3s

プロジェクトに脚本家を追加する

次に、Puppeteer と Jest を削除し、Playwright を追加しました。

 ~/project$ pnpm remove \ babel-jest jest jest-puppeteer @testing-library/jest-dom ~/project$ $ pnpm create playwright Getting started with writing end-to-end tests with Playwright: Initializing project in '.' ✔ Do you want to use TypeScript or JavaScript? · JavaScript ✔ Where to put your end-to-end tests? · tests ✔ Add a GitHub Actions workflow? (y/N) · false ✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · false ✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo pnpm exec playwright install-deps')? (y/N) · false Installing Playwright Test (pnpm add --save-dev @playwright/test)… … Installing Types (pnpm add --save-dev @types/node)… … Done in 2.7s Writing playwright.config.js. Writing tests/example.spec.js. Writing tests-examples/demo-todo-app.spec.js. Writing package.json.


また、 package.jsonから Jest 構成セクションも削除しました。

Playwright を Chromium のみを使用するように設定

Playwright テストは、Chrome、Firefox、Safari で実行できます。Chrome に焦点を当てていたため、生成されたplaywright.config.jsファイルのprojectsセクションから他のブラウザーを削除しました。

 /* Configure projects for major browsers */ projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, // { // name: 'firefox', // use: { ...devices['Desktop Firefox'] }, // }, // // { // name: 'webkit', // use: { ...devices['Desktop Safari'] }, // }, ], …

Puppeteer テストコードを Playwright テストコードと交換する

元のコードにはsrc/tests/puppeteer.test.jsに Puppeteer テスト ファイルがありました。そのファイルをtests/playwright.spec.jsに移動しました。次に、Playwright の規則を使用するようにテストを更新しました。これは非常にきれいにマッピングされました。新しいテスト ファイルは次のようになりました。

 const ROOT_URL = 'http://localhost:8080'; const { test, expect } = require('@playwright/test'); const inputSelector = 'input[name="name"]'; const submitButtonSelector = 'button[type="submit"]'; const greetingSelector = 'h5#greeting'; const name = 'John Doe'; test.beforeEach(async ({ page }) => { await page.goto(ROOT_URL); }); test.describe('Playwright link', () => { test('should navigate to Playwright documentation page', async ({ page }) => { await page.click('a[href="https://playwright.dev/"]'); await expect(page.title()).resolves.toMatch('| Playwright'); }); }); test.describe('Text input', () => { test('should display the entered text in the text input', async ({ page }) => { await page.fill(inputSelector, name); // Verify the input value const inputValue = await page.inputValue(inputSelector); expect(inputValue).toBe(name); }); }); test.describe('Form submission', () => { test('should display the "Hello, X" message after form submission', async ({ page }) => { const expectedGreeting = `Hello, ${name}.`; await page.fill(inputSelector, name); await page.click(submitButtonSelector); await page.waitForSelector(greetingSelector); const greetingText = await page.textContent(greetingSelector); expect(greetingText).toBe(expectedGreeting); }); });

start-server-and-test削除し、代わりに Playwright の webServer を使用します。

React アプリをテストするには、まず別のプロセスで ( http://localhost:8080で) 起動してから、テストを実行する必要がありました。これは、Puppeteer を使用する場合でも Playwright を使用する場合でも同じです。Puppeteer の場合、Heroku の例ではstart-server-and-testパッケージが使用されていました。


ただし、テストを実行する前にアプリを起動するように Playwright を設定できます。これは非常に便利です。


プロジェクトからstart-server-and-test削除しました。

 ~/project$ pnpm remove start-server-and-test


playwright.config.jsで、下部の webServer セクションのコメントを解除し、次のように変更しました。

 /* Run your local dev server before starting the tests */ webServer: { command: 'pnpm start', url: 'http://127.0.0.1:8080', reuseExistingServer: !process.env.CI, },


次に、元のpackage.jsonファイルからtest:ciスクリプトを削除しました。代わりに、テスト スクリプトは次のようになりました。

 "scripts": { … "test": "playwright test --project=chromium --reporter list" },

ローカルマシンに Playwright ブラウザをインストールする

Playwright は、テストに使用する最新のブラウザ バイナリをインストールします。そのため、ローカル マシンでは、Playwright の Chromium バージョンをインストールする必要がありました。

 ~/project$ pnpm playwright install chromium Downloading Chromium 130.0.6723.31 (playwright build v1140) from https://playwright.azureedge.net/builds/chromium/1140/chromium-linux.zip 164.5 MiB [====================] 100%


注: Heroku の Chrome for Testing ビルドパックは、テストに使用するブラウザをインストールします。Playwright が独自のブラウザをインストールするのに時間とリソースを費やすのではなく、そのブラウザを使用するように CI を設定します。

ローカルでテストを実行する

これで準備は完了です。次はローカルでテストを試してみる番です。

 ~/project$ pnpm test > playwright test --project=chromium --reporter list Running 3 tests using 3 workers ✓ 1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (911ms) ✘ 2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (5.2s) ✓ 3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (959ms) ... - waiting for locator('a[href="https://playwright.dev/"]') 13 | test.describe('Playwright link', () => { 14 | test('should navigate to Playwright documentation page', async ({ page }) => { > 15 | await page.click('a[href="https://playwright.dev/"]'); | ^ 16 | await expect(page.title()).resolves.toMatch('| Playwright'); 17 | }); 18 | });


ああ、その通りです。アプリ内のリンクが Puppeteer ではなく Playwright のドキュメントに移動することを期待するようにテストを変更しました。19 行目のsrc/App.js更新する必要がありました。

 <Link href="https://playwright.dev/" rel="noopener"> Playwright Documentation </Link>


さて、もう一度テストを実行する時間になりました...

 ~/project$ pnpm test > playwright test --project=chromium --reporter list Running 3 tests using 3 workers ✓ 1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (1.1s) ✓ 2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (1.1s) ✓ 3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (1.1s) 3 passed (5.7s)

テストに合格しました! 次は、Heroku CI に移行するときです。

CI パイプラインを使用するために Heroku にデプロイする

Heroku ブログ投稿の指示に従って、Heroku CI パイプラインでアプリをセットアップしました。

Herokuパイプラインを作成する

Heroku で新しいパイプラインを作成し、フォークした GitHub リポジトリに接続しました。



次に、アプリをステージングに追加しました。



次に、 「テスト」タブに移動して、 「Heroku CI を有効にする」をクリックしました。



最後に、 app.jsonファイルを変更して、 npm test:ci呼び出すように設定されたテスト スクリプトを削除しましたpackage.jsonファイルからtest:ciスクリプトはすでに削除してありましたpackage.jsontestスクリプトが使用されるようになり、Heroku CI はデフォルトでそのスクリプトを検索するようになりました。


Chrome for Testing ビルドパックを使用するように設定された私のapp.jsonファイルは次のようになります。

 { "environments": { "test": { "buildpacks": [ { "url": "heroku-community/chrome-for-testing" }, { "url": "heroku/nodejs" } ] } } }

初期テスト実行

コードを GitHub にプッシュすると、Heroku CI でテスト実行がトリガーされました。




テスト実行は失敗しましたが、心配していませんでした。Playwright の設定がいくつか必要になることはわかっていました。


テスト ログを調べてみると、次のことがわかりました。


 Error: browserType.launch: Executable doesn't exist at /app/.cache/ms-playwright/chromium-1140/chrome-linux/chrome


Playwright は Chrome ブラウザ インスタンスを探していました。CI テスト セットアップの一部として、 playwright install chromiumコマンドを使用してインストールできました。しかし、それでは Chrome for Testing ビルドパックの目的が台無しになってしまいます。Chrome はすでにインストールされていたので、それを適切に指定するだけで済みました。


Heroku のテスト設定ログを振り返ってみると、次の行が見つかりました。

 Installed Chrome dependencies for heroku-24 Adding executables to PATH /app/.chrome-for-testing/chrome-linux64/chrome /app/.chrome-for-testing/chromedriver-linux64/chromedriver Installed Chrome for Testing STABLE version 130.0.6723.91


つまり、私が使用したいブラウザは/app/.chrome-for-testing/chrome-linux64/chromeにありました。Playwright でそこを検索するだけで済みます。

Playwright がインストールされている Chrome ブラウザを見つけるのを手伝う

注:ここでの細かい詳細に興味がない場合は、このセクションをスキップして、下にある完全なapp.jsonをコピーしてください。これで、Heroku CI で Playwright を起動して実行するために必要なものが揃います。


Playwright のドキュメントで、すべてのブラウザ インストールにカスタムの場所を使用したかどうかを Playwright に伝える環境変数を設定できることが分かりました。その環境変数はPLAYWRIGHT_BROWSERS_PATHです。そこから始めることにしました。


app.jsonでは、次のようにenv変数を設定します。

 { "environments": { "test": { "env": { "PLAYWRIGHT_BROWSERS_PATH": "/app/.chrome-for-testing" }, ...


CI でのテストで何が起こるかを確認するために、コードを GitHub にプッシュしました。


予想通り、再び失敗しました。ただし、ログ エラーには次のように表示されました。

 Error: browserType.launch: Executable doesn't exist at /app/.chrome-for-testing/chromium-1140/chrome-linux/chrome


かなり近づきました。私はこうすることにしました:


  • Playwright が Chrome ブラウザを配置すると想定する場所に必要なフォルダを作成します。次のようなコマンドになります。
 mkdir -p "$PLAYWRIGHT_BROWSERS_PATH/chromium-1140/chrome-linux"


  • このフォルダに、Heroku ビルドパックによってインストールされた Chrome バイナリを指すシンボリックリンクを作成します。次のようになります。
 ln -s \ $PLAYWRIGHT_BROWSERS_PATH/chrome-linux64/chrome \ $PLAYWRIGHT_BROWSERS_PATH/chromium-1140/chrome-linux/chrome


しかし、これが将来にわたって有効かどうかは心配でした。 最終的に、Playwright は新しいバージョンの Chromium を使用するようになり、 chromium-1140フォルダーのようには見えなくなります。 Playwright がどこに表示されるかはどうすればわかるのでしょうか?


そのとき、ブラウザのインストールの予行演習ができることを発見しました。

 ~/project$ pnpm playwright install chromium --dry-run browser: chromium version 130.0.6723.31 Install location: /home/alvin/.cache/ms-playwright/chromium-1140 Download url: https://playwright.azureedge.net/builds/chromium/1140/chromium-linux.zip Download fallback 1: https://playwright-akamai.azureedge.net/builds/chromium/1140/chromium-linux.zip Download fallback 2: https://playwright-verizon.azureedge.net/builds/chromium/1140/chromium-linux.zip


「インストール場所」の行は重要です。PLAYWRIGHT_BROWSERS_PATH PLAYWRIGHT_BROWSERS_PATH設定すると、次のようになります。

 ~/project$ PLAYWRIGHT_BROWSERS_PATH=/app/.chrome-for-testing \ pnpm playwright install chromium --dry-run browser: chromium version 130.0.6723.31 Install location: /app/.chrome-for-testing/chromium-1140 ...


それが私が望んでいたことです。ちょっとしたawkマジックを使って、これを実行しました:

 ~/project$ CHROMIUM_PATH=$( \ PLAYWRIGHT_BROWSERS_PATH=/app/.chrome-for-testing \ pnpm playwright install --dry-run chromium \ | awk '/Install location/ {print $3}' ) ~/project$ echo $CHROMIUM_PATH /app/.chrome-for-testing/chromium-1140


これらすべてを理解したら、あとはapp.jsontest-setupスクリプトを追加するだけです。 PLAYWRIGHT_BROWSERS_PATHはすでにenvに設定されているため、スクリプトは少しシンプルになります。最終的なapp.jsonファイルは次のようになります。

 { "environments": { "test": { "env": { "PLAYWRIGHT_BROWSERS_PATH": "/app/.chrome-for-testing" }, "buildpacks": [ { "url": "heroku-community/chrome-for-testing" }, { "url": "heroku/nodejs" } ], "scripts": { "test-setup": "CHROMIUM_PATH=$(pnpm playwright install --dry-run chromium | awk '/Install location/ {print $3}'); mkdir -p \"$CHROMIUM_PATH/chrome-linux\"; ln -s $PLAYWRIGHT_BROWSERS_PATH/chrome-lin ux64/chrome $CHROMIUM_PATH/chrome-linux/chrome" } } } }


test-setup何をするのかを簡単に説明します。


  1. PLAYWRIGHT_BROWSERS_PATHを考慮して、 playwright install -- dry-runawkを使用して、Playwright が Chrome ブラウザを検索するルート フォルダを決定します。これをCHROMIUM_PATH変数の値として設定します。


  2. CHROMIUM_PATH/chrome-linuxに新しいフォルダー (および必要な親フォルダー) を作成します。これは、Playwright がchromeバイナリを検索する実際のフォルダーです。


  3. そのフォルダーに、Chrome の Heroku ビルドパックのインストール ( /app/.chrome-for-testing/chrome-linux64/chrome ) を指すシンボリック リンクを作成します。

再度テストを実行する

更新したapp.jsonファイルを使用すると、Playwright はビルドパックから Chrome インストールを使用できるようになります。もう一度テストを実行するときが来ました。




成功!


test-setupスクリプトは期待どおりに実行されました。



Playwright はchromeバイナリにアクセスしてテストを実行し、合格しました。



結論

私の Web アプリケーションのエンドツーエンドのテストは、それほど面倒ではなくなってきているので、ますます優先しています。最近では、Playwright も頻繁に使用しています。Playwright は柔軟で高速です。そして、Heroku CI の Chrome for Testing ビルドパックを使用して Playwright を稼働させるための作業 (私と皆さんのために!) が完了したので、ブラウザー自動化テスト スイートの構築を再び開始できます。


このウォークスルーのコードは私のGitHub リポジトリで入手できます。


楽しいコーディングを!