技術開発チーム・運用技術開発担当(通称opdev)の辰已です。
opdevは社内のさまざまなプロダクトの開発・保守運用を行っており、日々業務効率改善、ハートビーツの価値向上に繋がる技術開発・情報発信を行っています。
先日、opdevで開発した社内向けのプロダクトに対して、Visual Studio Code(以下VS Code)とPlaywrightを使ってE2Eテストを実施しました。 セットアップが簡単で、使い勝手も良かったので、今回はVS CodeとPlaywrightを使ったE2Eテストの実施方法を紹介します。
Playwrightとは
PlaywrightはE2Eテストやブラウザ自動操作用のフレームワークで、Microsoftがオープンソースで開発をしています。 他によく使われるE2Eテストフレームワークには、Selenium、Puppeteer、Cypressがあります。npmパッケージのダウンロード数の推移を確認できるnpm trendを見ると、Playwrightは2024年5月中頃に首位だったCypressを追い越し、パッケージのダウンロード数がトップになっています。
Playwrightの特徴は以下の通りです。
- Any browser • Any platform • One API
クロスブラウザ、クロスプラットフォーム、複数言語で利用可能 - Resilient • No flaky tests
自動ウェイトによりタイミングの調整が不要 - No trade-offs • No limits(※1)
複数ブラウザ、タブにも対応 - Full isolation • Fast exec
高速な実行、認証状態保持による繰り返しログインの排除 - Powerful Tooling
テストコード生成のための操作記録、テスト失敗時のさまざまな解析ツール群
Playwrightは後発のフレームワークであり、他のテストフレームワークの課題を改善している点が大きな特徴です。
※1. おそらくtrade-offs
の単語はCypressのTrade-offsを意識しているのでしょう。
Playwrightの導入
実際にVS CodeにPlaywrightを導入してみましょう。 MicrosoftはPlaywrightだけでなく、VS Code向けのPlaywright拡張機能も提供してくれています。周辺環境まで整備してくれているのは嬉しいですね。 なお、VS Codeの操作方法については本筋から外れるため割愛します。
- 拡張機能をインストールする
VS CodeでPlaywright Test for VSCodeを検索し、 installボタンをクリックして拡張機能をインストールします。 - プロジェクトを開く
テスト用プロジェクトを作成するディレクトリを開いておきます。今回はディレクトリ名をplaywright_sampleという名前で作成しました。 - Playwrightのインストール
コマンドパレットからtest: Install Playwright
を選択してPlaywrightをインストールします。
選択肢はそのままで問題ありません。Firefox不要、WebKit不要などがあれば適宜変更してください。
これだけで環境構築が完了です。とても簡単ですね!
動作確認
実際にPlaywrightを動かしてみましょう。実行対象のテストコードはtests
ディレクトリ以下(※2)のファイルになります。
VS Codeのアクティブバーからテストエクスプローラーを開き、実行したいテスト名の横にある再生マークをクリックしてください。テスト結果がTest Result
ターミナルに表示されたらOKです。
また、デバッガーを起動したい場合は、実行したいテスト名の横にある虫付き再生マークをクリックしてください。
これだけでデバッガーが使えます!launch.json
の作成・パスの調整など、いろいろな設定をすることなくデバッグ環境まで構築できるのはとても嬉しいですね。
※2. playwright.config.ts
のtestDir
にデフォルトで./tests
が指定されているためです。
テストへの適用
実際にフロントエンドとバックエンドを分離した構成のアプリケーションをテストしてみましょう。 テスト対象のサンプルシステムは以前のブログにて作成したものがあるため、それを利用します。
サンプルシステムの構成は以下のようになっています。
種類 | URL | 備考 |
バックエンド | http://127.0.0.1:8081 | /item のエンドポイントでアイテムの情報を返す |
フロントエンド | http://127.0.0.1:8080 | バックエンドの/itemエンドポイントで取得したデータをブラウザに表示する |
サンプルシステムの起動方法は以下の各リポジトリのREADMEを参照してください。
レコード機能を使ってテストコードを作成する
ゼロからテストコードを手で書くことも可能ですが、非常に手間がかかってしまうためオススメできません。Playwrightのレコード機能を利用しましょう。 レコード機能は、ブラウザでの操作を記録してくれる機能です。実施したいテストを画面上で操作するだけで、Playwrightが自動的に操作に対応するテストコードを作成してくれます。 以下で表示の確認、表示文字列の確認、設定値の確認を行うテストの例を作成します。
記録の開始
VS Codeのアクティブバーからテストエクスプローラーを開き、PlaywrightのアコーディオンからRecord newを選択してブラウザを起動します。
テスト対象のページにアクセス
表示されたブラウザのURLに127.0.0.1:8080を入力してフロントエンドにアクセスします。
ブラウザに
openapi_front_sample
が表示されていることを確認するテストの作成ブラウザ上部中央のパレットから
Assert visibility
を選択し、表示確認対象の要素を選択します。
選択し終えるとテストコードが追加されます。
ブラウザに想定した文字列が正しく表示されているかを確認するテストの作成
ブラウザ上部中央のパレットから
Assert text
を選択し、比較対象の要素を選択します。比較対象に表示される想定の文字列を設定します。
設定し終えるとテストコードが追加されます。
ブラウザに想定したInputの値が正しく設定されているかを確認するテストの作成
ブラウザ上部中央のパレットから
Assert value
を選択し、比較対象の要素を選択します。
選択し終えるとテストコードが追加されます。必要な場合は適宜値を設定してください。
記録の終了
ブラウザ上部中央のパレットからRecord
の赤丸をクリックします。
上記操作後、tests/test-1.spec.ts
には以下のようなテストコードが生成されます。
import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { await page.goto('http://127.0.0.1:8080/'); await expect(page.getByRole('heading', { name: 'openapi_front_sample' })).toBeVisible(); await expect(page.getByRole('main')).toContainText('{"name":"test","description":"description","price":10,"tax":1}'); await expect(page.getByRole('textbox')).toHaveValue('10'); });
もちろん、このテストコードを手で修正することも可能です。 とりあえずレコード機能を使ってざっくりテストを作り、細かな修正は後ほど手で直す、とすれば毎回DOMを調べなくても良いので、効率よくテストコードが作成できます。
レスポンスをモックしてみる
E2Eテストでは他システムも含め、できる限り本番と同じ環境でテストを行うことが理想です。しかし、実際にデータが書き込まれてしまうと困る、意図的にエラーを発生させることが難しい場合など、どうしてもモックを利用せざるを得ないケースもあります。そのようなときに便利なのがfulfillです。fulfillは、指定したURLのレスポンスをモックする関数です。Playwrightにデフォルトで含まれている関数なので、追加のパッケージをインストールする必要はありません。
試しに、APIサーバーのレスポンスをmock-data
に変更して実行してみましょう。
import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { await page.route('http://127.0.0.1:8081/item', async (route) =>{await route.fulfill({json:'mock-data'})}); // この1行を追加 await page.goto('http://127.0.0.1:8080/'); await expect(page.getByRole('heading', { name: 'openapi_front_sample' })).toBeVisible(); await expect(page.getByRole('main')).toContainText('{"name":"test","description":"description","price":10,"tax":1}'); await expect(page.getByRole('textbox')).toHaveValue('10'); });
APIサーバーのitemエンドポイントのレスポンスをmock-data
に書き換えました。URLを指定し、そのレスポンスを定義するだけです。
この状態で、先ほどのテストを実行してみましょう。
Error: expect(locator).toContainText(expected) Locator: getByRole('main') Expected string: "{\"name\":\"test\",\"description\":\"description\",\"price\":10,\"tax\":1}" Received string: "\"mock-data\""
以前はパスしていたテストがエラーになります。
Expectedが変更前のAPIのJSONになっていますが、Receivedはmock-data
になっています。APIサーバーのレスポンスを上書きできていますね。
Playwrightには他にもさまざまな便利な機能があります。興味がある方は公式ドキュメントをご覧ください。
おわりに
本記事では、VS CodeとPlaywrightを使ったE2Eテストの実施方法を紹介しました。他にもさまざまなテスト用関数や、アクション機能などがありますが、今回はグラフィカルに操作可能な部分に焦点を当てて紹介してみました。 簡単な例でしたが、少しでも参考になれば幸いです。