$30 off During Our Annual Pro Sale. View Details »

Playwright で一番小さく始める VRT と、次のステップの選択肢

Playwright で一番小さく始める VRT と、次のステップの選択肢

2024/02/21 ビジュアルリグレッションテストツール4選!ユーザーが語る各ツールのメリット で発表したスライドです。
https://trident-qa.connpass.com/event/308664/

参照したURL

- https://playwright.dev/docs/test-snapshots
- https://zenn.dev/mh4gf/articles/tiny-vrt-with-github-actions
- https://tech.route06.co.jp/entry/2023/03/29/080000

Hirotaka Miyagi

February 21, 2024
Tweet

More Decks by Hirotaka Miyagi

Other Decks in Technology

Transcript

  1. 自己紹介 Hirotaka Miyagi / @MH4GF 最近はフロントエンド多め GraphQL, GitHub Actions, 静的解析が好き

    ROUTE06, inc. フルリモートワークの会社で北海道から沖縄まで メンバーが在籍しています! 2
  2. Playwright とは Microsoft 製の E2E テストツール Cross-Browser ... Chromium, Webkit,

    Firefox, Mobile Chrome, Mobile Safari などを サポート Auto-wait ... 操作する前に、要素が操作可能になるまで待機してくれる Codegen ... ブラウザでの操作をコードに変換してくれる VSCode 拡張がめっちゃ便利 8
  3. 撮影フェーズ - 柔軟なカスタマイズ 例えばここでダークモードへの切り替えを追加してみる import { test, expect } from

    "@playwright/test"; test("example test", async ({ page }) => { await page.goto("http://localhost:3000"); // Testing Library ライクな API で要素を取得して操作 await page.getByRole("button", { name: "Toggle dark mode" }).click(); await page.screenshot(); }); 11
  4. 比較フェーズ toHaveScreenshot() でスナップショットテストができる import { test, expect } from "@playwright/test";

    test("example test", async ({ page }) => { await page.goto("http://localhost:3000"); await expect(page).toHaveScreenshot(); }); pixelmatch というツールを内部的に利用している 12
  5. VRT を小さく始めるための指針 Q: どのツールを使う?インフラは何を用意すれば良い? A: Playwright と GitHub Actions 以外のツールを使わない

    Q: 比較元のスクリーンショットはどのように用意する? A: 本番環境と PR 環境の両方を都度撮影する Q: 差分確認のビューワーはどのように用意する? A: GitHub の Artifacts に test-results を保存し、都度ダウンロードする 18
  6. Playwright のテストファイル // ./src/__test__/vrt.test.ts import type { Page } from

    "@playwright/test"; import { test, expect } from "@playwright/test"; type TargetPage = Record<"name" | "path", string>; // 撮影したいページのリスト const targetPages: TargetPage[] = [ { name: "home", path: "/", }, ]; for (const targetPage of targetPages) { test(targetPage.name, async ({ page }) => { await page.goto(targetPage.path); // スクリーンショットを撮る。TypeScript で書けるので、必要に応じて前処理を追加できる await expect(page).toHaveScreenshot(); }); } 20
  7. package.json 2 つの script を追加 --update-snapshots はスナップショットを更新するためのオプション { "scripts": {

    "test:vrt:screenshots": "playwright test --update-snapshots", "test:vrt:compare": "playwright test" } } 21
  8. GitHub Actions のワークフロー # .github/workflows/vrt.yml # 該当のstep だけ抜粋 # 本番環境に対してスクリーンショットを撮る。このスクリーンショットが比較元となる

    - run: pnpm test:vrt:screenshots env: BASE_URL: https://example.com/ # デプロイが成功した Preview 環境に対してスクリーンショットを撮り、比較する - run: pnpm test:vrt:compare env: BASE_URL: ${{ github.event.deployment_status.environment_url }} # 失敗時に理由がわかるよう、失敗したスクリーンショットをアップロードする - name: Upload failed screenshots if: failure() uses: actions/upload-artifact@v3 with: name: vrt-failed-screenshots-${{ github.sha }} path: test-results 22
  9. 運用 Preview 環境へのデプロイ で発火する CI として VRT を動かします 成功時 UI

    のデグレードはないですね!ということで、PR のレビュープロセスやマージに進みま しょう。 失敗時 UI の差分が発生しているので、以下の項目をチェックします。 UI の変更が意図したものでない: UI のデグレードが検知できましたね!開発に戻り 実装を修正しましょう。 UI の変更が意図したものである: CI は落ちたままですが、そのまま PR のレビュープ ロセスに進みましょう。 23
  10. Story に対してスクリーンショットを撮りたい 自前実装: Story のパスを列挙する ツールの採用: 撮影フェーズを @storybook/test-runner or storycap

    に切り替える @storybook/test-runner は 各 Story を「レンダリング」と「Play Function の実 行」を行うテストケースに変換・実行してくれる スクリーンショットの機能をデフォルトで提供しているわけではないが、内部的 に Playwright が利用されていて自前処理を差し込めるため、スクリーンショット を撮ることができる 27
  11. VRT 基盤の運用コストをできるだけ下げたい SaaS の採用: 全フェーズを Chromatic, lost-pixel に切り替える 単純な差分確認だけでなく、UI レビューや

    storybook のホスティングも可能 差分がある際に Pull Request の Checks で fail させるなどの細かい機能も便利 金銭的なコストがかかるのはデメリット ( 大規模プロジェクトになったときのパフォーマンスチューニングがどれだけで きるのかが気になる) 29