ビジュアルリグレッションテストについて ライブラリの種類について 入門の入門

Published: 2023年8月12日 by tomsato

ビジュアルリグレッションテストについて

ビジュアルリグレッションテストとは

変更を加える前後でスクリーンショットを比較し、比較検証するテストのこと

目視で確認している「見た目」の変化を機械的に検出する

→ キャプチャ(画像)の差分を見ているため、1pxでも違う箇所があればエラーとして検出される

参考:スナップショットテストとは

似たようなテストとして、スナップショットテストがある、こちらは変更を加える前後でコンポーネントの出力(スナップショット)を取得し、比較検証するテストのこと

VRT(ビジュアルリグレッションテストは省略してVRTともいう)はユーザーが見る視覚的要素の差分を見るのに対して、こっちはマークアップそのもの(HTML)の差分を見る

スナップショットテストではCSS ModuleでのCSS変更した場合には差分として出してくれないかも?

ビジュアルリグレッションテストの必要性

ボタンなど共通のコンポーネントの見た目を変更した際に全呼び出し箇所で表示崩れしていないかを確認するのは面倒

意図していない場所で表示崩れしてしまっていないか影響の確認まで考えると大変

→ ビジュアルリグレッションテストがあることでページ全体を通して意図していない差分がないかを確認できる

またこういったテストがない場合のやりがちな開発アプローチは「すでにある定義には触れない」ということでリファクタリング等はせず追加改修で誤魔化すというアプローチになりがちになってしまう

→ 場当たり的な対応となり気がついたら闇深いコードになってしまう、こういったテストがあることでリファクタリングしようという考えを持ちやすくなるメリットもある

ビジュアルリグレッションテストのライブラリの種類

ライブラリ選択肢、組み合わせが多い問題

ビジュアルリグレッションテストのやり方を調べると多数のライブラリを目撃する

  • Cypress
  • Playwright
  • reg-suit + Storycap
  • 他 多数

今回ビジュアルリグレッションテストについてネット検索をしていると

  • いろんなライブラリが出てきてよくわからない…
  • どういったものを使えばいいの?
  • なんでライブラリの組み合わせをしているの?

と疑問を持ったため、ライブラリの種類についてまとめてみる

ビジュアルリグレッションテストのライブラリの種類

① E2Eテストフレームワーク

Cypress、Playwright、Puppeteer などが挙げられる

E2Eテストフレームワークなのでブラウザの操作ができる、操作の一環でスクリーンショットができる

つまりE2Eテストの延長でVRTが実施できる

Playwrightは単独でスクリーンショットの比較検証もできて、Cypressは単独ではできないがcypress-image-snapshotを使ってVRTテストを行えるとか

② ビジュアルリグレッションテストに特化したライブラリ

jest-image-snapshot、reg-suit、reg-cli、BackstopJS などが挙げられる

名前の通りVRTを実施するために作成されたライブラリとなっている

reg-suitはスクリーンショットの比較はできるが、スクリーンショットを撮ること自体はできないので他のライブラリと組み合わせる必要あり

BackstopJSハスクリーンショット取得、比較両方できる

③ コンポーネントエクスプローラーツール

メモ:コンポーネントエクスプローラーツールとは、UIコンポーネントが独立した状態でどのように見えるのか比較検証するツール

StoryBookとかで、Storycapと組み合わせることでコンポーネント単位でスクリーンショットが撮れるとか

比較検証は別のツールを使う必要がありそう

どのライブラリを選択するか

以下観点がありそう

  • E2Eテストを既に使っているか、使う予定があるか
    • その場合はE2Eテストフレームワークを主軸に考えるのが良さそう
      • E2Eテストフレームワークと、VRTライブラリで別のものを使うとそれぞれで学習コストがかかるため、同一のものを使うのが望ましいかも
  • StoryBookを既に使っているか、コンポーネント単位でVRTテストしたいか
    • その場合はStoryBook + Storycap + α を組み合わせる選択肢が上がりそう
      • 逆にStoryBookに依存したくない場合は選択肢からは除外するべき
  • 差分をどのように見たいか
    • jest-image-snapshotでは画像の差分があった際にdiffの画像を見ることができる
      • イメージとしては後述する ※① のような形になる
      • reg-suit、Playwright、BackstopJSはレポート画面を出すことができて、差分を視覚的に確認することができる
        • イメージとしては後述する ※② のような形になる

ビジュアルリグレッションテストを触ってみる

選択したライブラリ

今回は以下の点を考慮してPlaywrightを使ってみました

  • E2Eテストの延長でVRTをやりたいため
  • Playwright単体でスクリーンショット取得、比較ができる
  • 差分が見やすい
  • スナップショットはローカルに置いて確認ができる (他のライブラリでもできそうではあるが)
  • テストを並列で実行できる (他のライブラリでもできそうではあるが)

テストページ作成

今回は React / Next.js のサンプルページを用意する

$ npx create-next-app@latest
npx: 1個のパッケージを1.484秒でインストールしました。
✔ What is your project named? … sample-vrt
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias? … No / Yes

$ cd sample-vrt/

確認環境について

react@18.2.0
next@13.4.13

$ node -v
v18.17.1

サンプルページ起動

$ npm run dev

http://localhost:3000

今回はこの画面を元に更新していく

vrt 01

Playwrightの準備

$ npm init playwright@latest
✔ 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

サンプルのテストファイルが既に作成されているためlocalhostを見るように修正

$ vim tests/example.spec.ts
import { test, expect } from '@playwright/test';

test('example test', async ({ page }) => {
  await page.goto('http://localhost:3000/');
  await expect(page).toHaveScreenshot({ fullPage: true });
});

ビジュアルリグレッションテスト実施

初回は比較する画像がないためエラーになるが、2回目は問題なく成功する

$ npx playwright test

Running 3 tests using 3 workers
  3 passed (4.5s)

To open last HTML report run:

  npx playwright show-report

次にちょろっとページを修正して再度テストを実施する

テストが失敗することを確認

$ npx playwright test

Running 3 tests using 3 workers
  1) [webkit] › example.spec.ts:3:5 › example test ─────────────────────────────────────────────────

    Error: Screenshot comparison failed:

...中略

  3 failed
    [chromium] › example.spec.ts:3:5 › example test ────────────────────────────────────────────────
    [firefox] › example.spec.ts:3:5 › example test ─────────────────────────────────────────────────
    [webkit] › example.spec.ts:3:5 › example test ──────────────────────────────────────────────────

  Serving HTML report at http://localhost:9323. Press Ctrl+C to quit.

ページに差分があるため、テストが失敗し、レポートページが自動で立ち上がる

vrt 02

手動で見たい場合は以下のコマンドで確認することができる

$ npx playwright show-report

修正前の画像(Expected)、修正後の画像(Actual)、差分画像(Diff)が表示される

差分画像について、差分があるところについてのみハイライトされるので凄くわかりやすい ※①

vrt 03

ちなみに該当箇所に「 hoge」という文字を追加していました

差分について視覚的に見ることもできるのでわかりやすい

vrt 04

差分を受け入れる際には以下のコマンドにて、スクリーンショットを更新することができる

$ npx playwright test -update-snapshots

メモ

ブラウザでページを表示し始めた際にローディング画像を出しつつ、非同期で表示データを取得している場合の書き方は以下

// #list というIDを持つ要素が表示されるまで待つ
const order Sent = page.locator('#list')
await orderSent.waitFor()

何も対策しないと、スクリーンショットの結果としてはローディングが取得できるが上記の書き方で非同期でのデータ取得に対応できる

わざわざsleepしてスクリーンショットを撮るとかしなくて良いので便利

当然のことながら目に見えないところの差分については追えない

select boxのオプション追加などは差分に出なさそう

逆にスナップショットテストだと差分には出そう

クリックや更新処理などユーザーの操作に応じたテスト単位でVRT実施は大変そう

というよりそこまでいくともうE2Eテストの領域に見える

最初はページ毎に1つ初期表示のスナップショットを確認するだけでも大分ようさそうな肌感

ページ数が多く、キャプチャが多いとその分GitHubにアップロードすることになることに注意

ライブラリによってはAmazon S3に置いてあるスクリーンショットを比較するとかができるため必要に応じて検討した方が良さそう

ビジュアルリグレッションテスト導入例

以下のようにCICDに組み込むのが良さそう

  • GitHubでプルリクエストを作成する
  • プルリクエスト単位でアプリケーションの動作確認環境を作成する
  • 作成した動作確認環境にてVRTテストを実施する
  • 失敗時には結果のレポート画面等を見れるようにしておく

すごいざっくりだがこのような自動化をしておくと良さげ

詳細なやり方については使っている環境によって大分異なるため割愛

ビジュアルリグレッションテストの効果

LINEの例

制作現場におけるビジュアルリグレッションテストの導入 - 「LINEのお年玉」4年目の挑戦

導入した効果として、導入後にバグが30%少なくなったとか

どの粒度まで導入しての結果なのかがわからなかったが、とりあえず数値としての実績が出ている

ソフトバンクの例

毎日1時間でWebページ1,000以上のうち1pxの変化を逃さない、ソフトバンクのE2Eビジュアルリグレッションテスト取り組みについて

1000ページ以上のWebページに導入して、月100万以上分の動作確認ん工数が削減できたとか

大分盛っていそうな気がするが、しかしページ数が多いアプリケーションについてはVRTの効果は存分に発揮しそう

終わりに

  • VRTのテストを書くこと自体は簡単そう
  • 自動化の仕組みについて、認証があるページなどは対応が面倒そうだが、一度作ってしまえば保守も簡単そう
  • 差分が出るたびにupdate-snapshotsを打たないといけないのは慣れていないと若干面倒に感じるかも
  • 差分箇所について見やすい、良き
  • 導入効果もありそう

つまりビジュアルリグレッションテストおすすめ!

コメントを書く

※ 個別に返信が必要な時のみご記入ください

※ Emailは公開されません

※ 承認されると名前・コメントが下記に表示されます

コメント一覧

最近の投稿

ビジュアルリグレッションテストについてまとめ、ネットで調べると数多くのライブラリがありどれがどんな立ち位置なのか全体像がわかりずらかったのでどんな種類があるのか入門の入門としてまとめます、またPlaywrightを使って実際に触ってみました

社内ツールなどの超小規模なAPIをGolangで実装する際にフレームワークを使うべきかを、実際にnet/httpを使った実装とフレームワークを使った実装を比較することでどれだけ優位性があるかを見ていきたいと思います。今回はフレームワークにはシンプルで使いやすそうなEchoを使うことにします。

vue-pdfを使ってNuxt.jsで作成しているアプリケーションに pdfスライドを表示させるサンプルを作成しました README.md通りに実装してもうまくいかないところがあったのでそのあたり含めてまとめます

Vue.js / Nuxt.jsにおけるログインの実装方法をまとめる Auth0やNuxt.jsのAuth Moduleとmiddlewareについて調べつつサンプルを作成することで理解を深める

コンポーネント設計について考える Atomic DesignやPresentational Component, Container Componentについてまとめつつ 自分だったらVue.js / Nuxt.jsでどういうコンポーネント設計にするかについてまとめます

カテゴリ一覧

タグ一覧