📸

PlaywrightでのVisual Regression TestをGithub ActionsでCIする

2022/08/22に公開

Playwrightでのテストが結構快適だと思っているものの、Visual Regression Testを実施した際にハマる部分があったのでまとめてみます。

最終的に出来上がったもの

https://github.com/Kanatani28/playwright-vrt

私の環境

  • M1 Mac
  • Node 18.5

プロジェクトを作成

公式ドキュメントに従って以下のような設定で適当なプロジェクトを作成します。
今回はGithub Actionsで動かしてみるので、CLIでworkflowのフォルダも一緒に作成しています。

# playwright-vrtという名前で作成
$ npm init playwright@latest playwright-vrt

Getting started with writing end-to-end tests with Playwright:
Initializing project in 'playwright-vrt'
✔ 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) · true

動作確認

$ cd playwright-vrt
$ npx playwright test
Running 3 tests using 3 workers

  3 passed (2s)

To open last HTML report run:

  npx playwright show-report

Github Actionsで動かしてみる

.github/workflows/playwright.ymlを少し編集します。
各種actionのバージョンをv2 -> v3に上げているのと、
Actionsのトリガーにworkflow_dispatchを追加して手動実行できるようにしています。

.github/workflows/playwright.yml
name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
  workflow_dispatch:
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: '14.x'
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright Browsers
      run: npx playwright install --with-deps
    - name: Run Playwright tests
      run: npx playwright test
    - uses: actions/upload-artifact@v3
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

この状態でGithubにpushするとPlaywrightのテストがGithub Actionsで実行されます。

Visual Regression Testしてみる

公式を参考にVRTしてみます。
最後の行に追記してVRTしています。

import { test, expect } from '@playwright/test';

test('homepage has Playwright in title and get started link linking to the intro page', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/Playwright/);

  // create a locator
  const getStarted = page.locator('text=Get Started');

  // Expect an attribute "to be strictly equal" to the value.
  await expect(getStarted).toHaveAttribute('href', '/docs/intro');

  // Click the get started link.
  await getStarted.click();

  // Expects the URL to contain intro.
  await expect(page).toHaveURL(/.*intro/);

  // VRT実行部分
  await expect(page).toHaveScreenshot("landing.png");
});

追記できたら実行してみます。
初回は画像データが無いので--update-snapshotsオプションを付けて実行することで画像データが用意されます。

$ npx playwright test --update-snapshots

testsディレクトリ下に画面キャプチャが用意されます。
これ以降--update-snapshotsをつけずに実行することで、VRTが実施できます。

# ↑で作成した画像と実施結果を比較する
$ npx playwright test

Github Actionsで動かす

ここまでローカルでのVRTができましたが、CIで回そうとすると失敗してしまうことがあります。
今回であればローカルで実行した際に取得される画像はMacで取得した画像ということになります。
Playwrightは画面キャプチャをOSプラットフォーム毎に作成するため、CIで動かしているLinuxで取得した画像が用意されてないというエラーが出てきます。

エラー例(landing-chromium-linux.pngというファイルが存在しない)
Running 3 tests using 1 worker
××F××F××F

  1) [chromium] › example.spec.ts:3:1 › homepage has Playwright in title and get started link linking to the intro page 

    Error: /home/runner/work/playwright-vrt/playwright-vrt/tests/example.spec.ts-snapshots/landing-chromium-linux.png is missing in snapshots.

      20 |
      21 |   // VRT実行部分
    > 22 |   await expect(page).toHaveScreenshot("landing.png");
         |                      ^
      23 | });
      24 |

        at /home/runner/work/playwright-vrt/playwright-vrt/tests/example.spec.ts:22:22

なのでLinuxでのキャプチャを事前に用意する必要があります。
今回はDockerを使って取得してみます。

DockerでのLinux用キャプチャ取得

以下のようなDockerfile, docker-compose.yml, .dockerignoreを用意します。

Dockerfile
FROM mcr.microsoft.com/playwright:v1.25.0-focal

WORKDIR /work

COPY package*.json ./

RUN npm ci

CMD ["npx", "playwright", "test"]
docker-compose.yml
version: '3'
services:
  playwright:
    build:
      context: .
    working_dir: /work
    volumes:
      - ./:/work
    network_mode: host
    command: npx playwright test
.dockerignore
node_modules

ビルド&実行してみます。

$ docker-compose build
$ docker-compose run playwright npx playwright test --update-snapshots

これでLinuxでのキャプチャが取得できます。

あとはPushしたらいい感じにCIされるはず・・・

と思いきや、まだこの状態では失敗してしまいます。
artifactをダウンロードしてから確認すると以下のように差分が出てきました。


Github Actions上で取得されたもの


ローカルのDockerで取得されたもの

Github ActionsのUbuntuの環境とPlaywrightのDocker Imageをベースにした環境でどうもフォント等が異なるようです。

とりあえずローカルと同じコンテナで実行がしたいと思ったのでこちらの記事と同じようにimageを指定して実行してみます。

.github/workflows/playwright.yml
name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
  workflow_dispatch:
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
+    container:
+      image: mcr.microsoft.com/playwright:v1.25.0-focal
    steps:...

今度はFirefoxのエラーが・・・

ここまでで実行してみると今度は以下のようにFirefoxのエラーが出ていました。

  1) [firefox] › example.spec.ts:3:1 › homepage has Playwright in title and get started link linking to the intro page 

    browserType.launch: Browser.enable): Browser closed.
    ==================== Browser output: ====================
    <launching> /ms-playwright/firefox-1344/firefox/firefox -no-remote -headless -profile /tmp/playwright_firefoxdev_profile-JAgBGP -juggler-pipe -silent
    <launched> pid=832
    [pid=832][err] Running Nightly as root in a regular user's session is not supported.  ($HOME is /github/home which is owned by uid 1001.)
    [pid=832] <process did exit: exitCode=1, signal=null>
    [pid=832] starting temporary directories cleanup
    =========================== logs ===========================
    <launching> /ms-playwright/firefox-1344/firefox/firefox -no-remote -headless -profile /tmp/playwright_firefoxdev_profile-JAgBGP -juggler-pipe -silent
    <launched> pid=832
    [pid=832][err] Running Nightly as root in a regular user's session is not supported.  ($HOME is /github/home which is owned by uid 1001.)
    [pid=832] <process did exit: exitCode=1, signal=null>
    [pid=832] starting temporary directories cleanup
    ============================================================

詳しいことはあまりわかりませんでしたが、playwrightのIssueを確認してみると一件それらしきものがヒットしました。

https://github.com/microsoft/playwright/issues/6500

Github側に問題があって私達には解決できない問題とのことで、HOME=/rootを指定してコマンドを実行することで回避できるそうです。
これを付与してとりあえずは各種ブラウザでテストが成功していることを確認できました。

.github/workflows/playwright.yml
@@ -21,7 +21,7 @@ jobs:
    - name: Install Playwright Browsers
      run: npx playwright install --with-deps
    - name: Run Playwright tests
-      run: npx playwright test
+      run: HOME=/root npx playwright test
    - uses: actions/upload-artifact@v3
      if: always()
      with:

所感

Playwrightを使ってVRTをしてみました。
VRTだとDOMの構造に囚われないテストができる反面、フォントなど、VRT以外のテストではそこまで気にしなかった部分でハマりました。
上手く取り入れることでフロントエンド修正時の影響範囲をより把握しやすくなるかもしれません。

昨今はフロントエンドでもPlaywrightを始め、Storybookやmswなど、便利なツールがどんどん出てきてテストが書きやすくなってきた印象があります。
フロントエンドでもテストをガンガン書いていきましょう!

GitHubで編集を提案

Discussion