PlaywrightでのE2Eテストを試しました
Playwrightとは、Microsoftが開発しているE2Eのテストフレームワークです。ここ2~3年で国内での採用事例が急増していて、現在の自動テストにおいて最も人気がある様子です。軽くGoogleで検索しただけで「○○からPlaywrightに移行しました」みたいな各社の開発blogがたくさん見つかります。
そこで、この記事ではWindowsでなるべく簡単にPlaywrightを使う方法を試してみます。
インストール
主に必要なのは、Node.jsとVisual Studio Code(略してVSCode)の2つです。
まず、Node.jsを公式サイトからダウンロードしてインストールします。VSCodeも同様に、公式サイトからダウンロードしてインストールします。
また、“Playwright Test for VSCode”という拡張機能もインストールします。拡張機能のページからインストールもできますし、VSCodeを開いて拡張機能をインストールする方法でもOKです。PlaywrightはPowerShellやコマンドプロンプトで操作するのですが、この拡張機能ではそれらが不要でPlaywrightを使えるようになります。
プロジェクトの作成
まずは、適当な空のフォルダーを作ります。フォルダーはどこでもいいのですが、次の2点だけ注意です。
- Program Filesなど管理者権限が必要な場所には置かない
- OneDriveやGDriveで同期される場所には置かない(重くなってしまうため)
ここでは、 “C:\Projects\lets-try-playwright” というフォルダーを作ります。
そしてVSCodeを開き「ファイル > フォルダーを開く (Ctrl+K, Ctrl+O)」で、作ったフォルダーを選択します。すると、まだ何もファイルがないので、このような画面になります。
VSCodeの画面で Ctrl + Shift + P
(CtrlとShiftを同時に押しながら、Pキー)を押すと、テキストの入力画面が出てきます。これはコマンドパレットという、あらゆる操作を検索できる機能です。ここに Install Playwright
と入力して出てきた「Install Playwright」を選択します。
チェックボックスが出てきますが、全部デフォルトのままOKを押します。
ダウンロードなどを少し待つと、こんな風にいろいろなファイルが作成されて完了します。
これでPlaywrightのプロジェクトを準備できました。「ターミナル」については使わないので、バツボタンで消してしまってOKです。
試しに実行してみる
フォルダーの中にある tests/example.spec.ts がサンプルなので、左側のファイル一覧から example.spec.ts をダブルクリックして開いてみます。
1つ目の”has title”というテストケースを試しに実行してみます。 test('has title', ...
の行の左にある▷マークを押してみると実行できます。
デフォルトだとブラウザは表示されず裏側でテストされる(ヘッドレスモード)ので地味ですが、完了したテストケースにはチェックマークがつきます。
Show browser
VSCodeの左側のサイドバーからテスト(フラスコのアイコン)をクリックすると、テストに関する項目を確認できます。下の方に「Playwright」という項目があり、スクロールしてさらに下にある「Show browser」にチェックを入れると、ブラウザが表示された状態でテストを実施できます。
またその上の「テストエクスプローラー」にはテストケースの一覧が表示されます。
“has title” は上で実施したので、もう1つの “get started link” を押し、三角のボタンを押してテストを実行してみます。
Show browserがONになっていると、先ほどと異なり実際にブラウザが起動してテストが実行されます。
Show trace viewer
「Show browser」の1つ下に「Show trace viewer」というチェックボックスがあります。これにチェックを入れて実行すると、各操作の履歴をスクリーンショットで確認できます。
失敗したテストの確認をしたいときやテストを作っているとき、テストがどんな挙動をするのかこのビューワーで確認できます。
各操作の前後でのスクリーショットや、各操作に対応するコードの表示、ネットワークログなど必要な機能は充実しているようです。
実際のプロジェクトで試してみる
続いて、用意されているサンプルでなく、実際のプロジェクトで使えるE2Eテストを作ってみます。今回はローカルで起動しているEC-CUBE (http://localhost:8080) を例に、商品を購入する一連の流れをテストケースにしてみます。
- サイトトップページの左上の虫眼鏡アイコンをクリックして、商品一覧ページを開く
- 商品一覧から、対象の商品をカートに入れる
- モーダルの「カートへ」ボタンをおして、カートページを開く
- カートページの「レジに進む」ボタンを押す
- ログイン画面が表示されるので、メールアドレスとパスワードを入力してログインする
- 注文手続きページでは、お支払方法に「代金引換」を選び「確認する」を押す
- 注文確認ページでは、「注文する」を押す
- 注文完了ページが表示されることを確認する
手動操作の記録
上で見たようなテストコードをかくのは面倒ですが、”codegen” という機能で手動の操作を記録して再現することができます。コードを1から手書きする必要はありません。
VSCodeから手動操作の記録をするには、TOOLSにある「Record new」を押します。ボタンを押すと、VSCode上で test-1.spec.ts というファイルが作成され、同時にブラウザが起動します。
まず、出てきたブラウザのURLバーに今回のテスト対象である http://localhost:8080 を入力してEnterを押します。すると、ブラウザはEC-CUBEの画面に遷移し、エディタ(VSCode)には await page.goto('http://localhost:8080');
が入力されます。
続けて、箇条書きのとおりの購入操作をブラウザ上で行います。そうして購入完了まで進むと、test-1.spec.ts に追記されたコードはこのようになりました。
await page.goto('http://localhost:8080/'); await page.getByRole('banner').getByRole('button').click(); await page.getByRole('listitem').filter({ hasText: 'チェリーアイスサンド ¥1 数量 カートに入れる' }).getByRole('button').click(); await page.getByRole('link', { name: 'カートへ進む' }).click(); await page.getByRole('link', { name: 'レジに進む' }).click(); await page.getByRole('textbox', { name: 'メールアドレス' }).click(); await page.getByRole('textbox', { name: 'メールアドレス' }).fill('test@localhost'); await page.getByRole('textbox', { name: 'メールアドレス' }).press('Tab'); await page.getByRole('textbox', { name: 'パスワード' }).fill('password'); await page.getByRole('button', { name: 'ログイン' }).click(); await page.getByText('代金引換').click(); await page.getByRole('button', { name: '確認する' }).click(); await page.getByRole('button', { name: '注文する' }).click();
page.getByRole
やpage.locator
などの関数でページ内の要素を選択し、click
したりfill
したりするコードになっています。詳細な中身は分からなくても、見た感じで page.getByRole('textbox', { name: 'パスワード' }).fill('password')
は、パスワードという名前のテキストボックスに “password” と入力しているのが分かると思います。(記事の文字表示だと分かりにくいですが、下にあるVSCodeのスクリーンショットを見れば分かりやすいです)
最後に、購入完了画面で「ご注文ありがとうございました」と表示されることを確認するようにしましょう。ページ内に表示されている “Assert visibility” ボタン(目のアイコン)を押してから確認したい要素をクリックします。すると、テストコードにその要素があることの検証コードが追加されます。
また、今回のケースではほとんど同じですが、隣の “Assert text” ボタン(abのアイコン)は文字検証の機能です。この機能では、画面内の指定要素に指定文字が含まれていることを検証できます。
2つを実行すると、上のコードに次の2つが追加されました。
await expect(page.getByRole('heading', { name: 'ご注文ありがとうございました' })).toBeVisible(); await expect(page.locator('h2')).toContainText('ご注文ありがとうございました');
録画終了みたいなアイコンをクリックしてブラウザを閉じれば記録終了です。最後に、テストケース名がデフォルトの 'test'
なので 'ログインして購入する'
に変更しておきます。今回は省略しますが、実際にはファイル名の変更などもするとよいです。
VSCodeで見たコード全文はこのようになります。
テストを実行してみる → エラー
それでは、手動操作で作ったテストコードを実施してみます。方法は上のサンプルのときと同じです。しかし実行してみると、残念ながらこんな画面になります。
エラーはあまり嬉しくないですが、どこでどんなエラーが起きたのかとても分かりやすいですね。どうやら「カートへ進む」ボタンが押せないまま、30秒経ったのでエラーになったみたいです。
トレースビューワーで見てみると、このような画面でした。「カートに入れる」を押しても「カートへ進む」のポップアップが表示されず、カート画面に遷移してしまったようです。
デバッグする (step by step)
エラーの概要は分かったので、次にどうすればテストが通るようになるかを調べます。それには、テストコードを1行ずつ実行するデバッグ機能(step by step)が便利です。
エラーが起きた行の手前、今回は6行目の左側の空白をクリックして赤い丸マークをつけます。これはブレークポイントと言って、実行を一時停止したい箇所の指定する機能です。そして、通常の「テストの実行」ではなく「テストのデバッグ」(虫のアイコン)をクリックして実行してみます。
ブラウザが起動して自動テストが始まりますが、赤い丸をつけた箇所でストップします。この状態で、VSCodeの画面にある「ステップオーバー (F10)」ボタンをクリックすると……
6行目の処理が実行され、「カートに入れる」ボタンが押されました。そして、モーダルと「カートへ進む」ボタンが正常に表示されました。ここでもう一度、ステップオーバー (F10)を押すと……
上の「カートへ進む」ボタンが押され、カート画面に遷移しました。
それ以降も1つずつ実行していくと、問題なく購入完了ページが表示されます。自動で実行したときは表示されなかった「カートへ進む」ボタンが、1つずつ手動で実行すると問題なく表示されているようです。
修正して再実行
「カートへ進む」ボタンが表示されるモーダルはJavaScriptで動いていることを考えると、おそらくページ内のJavaScriptが処理される前にボタンを押してしまっているのだと理解できます。
そこで、ちゃんとページが読み込み終わってから要素をクリックするようにテストコードを修正します。Playwrightでは await page.waitForLoadState('domcontentloaded');
と書くことで、ページ内のJavaScriptが読み込まれるまで待機することができるので、カートへ進むボタンを押す前にこのコードを追加します。
最終的にはこのようになりました。必要はなかったのですがページ遷移が影響しそうな部分に待機を追加して、ついでに不要なクリックなどの処理を削除して、かんたんにコメントを追加しました。これで、無事にテストが完了するようになりました
最後に
弊社QAチームが従来使っていた自動テストツールが使えなくなったと聞き、ちょうど私が個人的な開発でE2Eテストの導入を検討していたので、一番良さそうなPlaywrightを試してみました。
Playwrightは、英語ですが見やすい公式ドキュメントが充実していますし、
- スクリーンショットによる検証(画像差分でのテスト)
- GitHub Actionsでテスト実行の自動化
- マルチデバイスのエミュレーション
など、かなり機能面でも充実していて応用ができそうです。
新しめのフレームワークなので以前は情報が少なかったようですが、2025年現在では事例も多くなっています。試してみた感覚としては、導入の簡単さ・利便性・機能性はかなり高く、採用事例の多さに納得しました。Microsoftが開発しているOSSという安心感もありますし、おそらく一過性の流行では無くSeleniumやCypressの代わりとして今後も導入事例が増えていくのかなと思います。