初めに
この記事はcommmune Advent Calendar 2023の12日目として投稿されました
Playwright
PlaywrightはWebアプリのE2Eテストに用いられるNode.js上で動作するライブラリです。簡単にクロスブラウザ(Choromium, Firefox, Webkit)テストを実施できるので複数のブラウザをサポートするWebアプリ開発でのテストに最適です。
Playwrightの初期設定
Playwrightの公式サイトに沿ってPlaywright最新版のインストールを行います。
npm init playwright@latest
インストールの際に4つのオプションを選択できます。今回は以下のオプションでインストールします。
✔ Do you want to use TypeScript or JavaScript? · TypeScript
✔ 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 'npx playwright install')? (Y/n) · true
下記のファイルを指定階層(playwright_vrt)にインストールできます、これでplaywrightのインストールは完了です。playwright.config.ts
内でデフォルトでChormium,Firefox,Webkit環境でのテストが指定されていますのでテスト内容によってここを修正することで任意のブラウザを指定することができます。
Playwrightの実行
下記コマンドでサンプルコードを実行できます。実行しているコードはtests
フォルダにある'example.spec.ts'です。実行が完了するとtest-results
フォルダとplaywright-report
フォルダが同階層に生成され、'playwright-report'フォルダの中にテスト結果であるindex.html
が生成されます。
npx playwright test
(補足)
--ui
オプションをつけて実行するとテスト実行管理画面が開き、1段階づつテスト実行を追えるのでFlakyなテストコード修正やどこでテストが落ちているのかわからない時に便利です。
npx playwright test --ui
次に下記コマンドで実行結果を見ることができます。このレポートの中身としては上記のindex.html
に当たります。
npx playwright show-report
以上でPlaywrightの一連の流れは終わりです。次にPlaywrightを利用してVisual Regression Testを実装していきます。
Visual Regression Test
Visual Regression Testは開発が既存のUIに影響を与えていないかを確認するためのテスト手法です。
以前のUIと現在のUIの差分を比較してくれるのでUI影響確認に便利なテストです。一般的に多く普及しているライブラリ、ツールとしてはreg-suit
percy
Chromatic
などがあります。今回は、Playwrightの既存機能とオプションのみを用いてVisual Regression Testを実装していきます。
PlaywrightでVisual Regression Test
テスト環境準備
Visual Regression Test用のテスト環境を準備します。既存のWebサイトでも構わないですが今回はUI差分確認ができているかの確認をしたいためローカル環境にReactをインストールし初期設定画面を利用して差分確認を実施します。
npx create-react-app my-app
cd my-app
npm start
Playwright実装
PlaywrightでVisual Regression Testを実装するために標準装備されているtoHaveScreenshot()
を使用します。この機能はテスト中にスクリーンショットを撮影する機能ですが同時に、以前撮影したスクリーンショットとの差分を比較することができます。
初期インストールされたtests
フォルダの中のexample.spec.ts
を下記のように修正します。
import { test, expect } from '@playwright/test';
test('React Visual Regression Test', async ({ page }) => {
// go to localhost:3000
await page.goto('http://localhost:3000');
// Expects have screenshot
await expect(page).toHaveScreenshot();
});
今時点では比較のためのスクリーンショットが撮影されていないのでこの状態で実行すると比較対象がないためエラーとなります。そのため、一度下記コマンドを実行して比較対象となるスクリーンショットを撮影します。
npx playwright test --update-snapshots
実行に成功すると比較となるスクリーンショットが取得できました。取得したスクリーンショットは新しく生成されたexample.spec.ts-snapshots
フォルダにそれぞれのブラウザ毎格納されます。
最後に差分比較を実行します。
npx playwright test
現状は何もUIを変更していないので問題なく実行完了することができます(show-reportを見ても特にエラーは発生しない)。次に、UI変更が加えられた場合のケースについて紹介します。
UIに差分がある場合
先ずはReact側に差分を作るために../my-app/src/App.js
を修正しました。「Learn React」だった部分が「Playwright Regression Test」と表示されています。
この状態でPlaywrightを実行させるとUI差分が生じるのでエラーとなります。この時、test-results
フォルダにエラーとなった画像が保存されます。
どの部分でUI差分が生じたのかshow-reportから確認することができます。下記の画面についてはshow-reportのトップ画面から各ブラウザの詳細エラー画面に遷移することで確認できます。
画像内では赤い部分がUI差分を表しています。また、「Actulal」を選択すると期待しているUIと現在のUIの差分をバーを動かすことでリアルタイムで目視することができます。どの部分がUI差分起きているかわからない、という時に一目瞭然なので便利です。
toHaveScreenshot()のオプション
上記以外にもtoHaveScreenshot()にオプションを指定することで便利な使い方をすることができます。詳しくは公式サイトに記載ありますが、今回は自分が実際に使ってみて便利そうだったオプションについて紹介していきます。
フルスクリーン表示
Webアプリをフルスクリーンで表示してUI差分を取ることができます。スクロール処理が面倒な時などに便利です。boolean型でどちらかを指定することができます。
await expect(page).toHaveScreenshot({
fullPage: true
});
マスク指定(無視する動的コンテンツを指定)
Webアプリによっては動的なコンテンツがある場合E2Eが落ちる原因となってしまいます。その場合mask
オプションを使用することで動的なコンテンツのUI差分読み込みを回避することができます。
import { test, expect } from '@playwright/test';
test('example test', async ({ page }) => {
await page.goto('https://www.rakuten.co.jp/');
await expect(page).toHaveScreenshot({
mask: [
page.locator('.r-slideshow-item-image'),
page.locator('.video-section')
]
})
});
今回は例として楽天市場サイトを使用しています。楽天市場はユーザー毎によってログイン毎にTOP画面が変わるのでmask処理をしないとテストが落ちやすいです。
上の動画だとページに遷移する度にエラーとなりましたが、下の動画ではmask処理をしています。mask処理した範囲はピンクで表示されておりこの部分はUI差分に含まれません。これにより、テストをエラーなく完了することができました。
差分許容範囲指定
マスク指定するほどではないが許容したい差分範囲を操作したい時に使用します。範囲を広げることで自動テストが落ちにくくになりますがその反面厳密なUI確認には向いていないので多用はできない印象です。
await expect(page).toHaveScreenshot({
maxDiffPixelRatio: 0.05
});
CSSアニメーション停止
アニメーションが流れるWebアプリの場合Visual Regression Testの妨げになることが多いです。そのため、そのようなアニメーションを停止するオプションを入れることで安定なテストを実施することができます。animations
はboolean型ではなくdisabled
かallow
を指定する必要があるので注意です。
await expect(page).toHaveScreenshot({
animations: 'disabled'
});
その他便利なコマンド
今回はVisual Regression Testに焦点を当てましたが下記記事に便利なコマンドが纏められているので併用することでテスト内容を拡充することができます。
これだけはおさえておきたいplaywrightコマンド集