ぱんだツールズぱんだツールズ

技術背景

ビジュアルリグレッションテストとは ─ スクリーンショット比較でUIバグを防ぐ方法

約7分

CSSのちょっとした変更が、思わぬ場所のレイアウトを崩していた——フロントエンドの開発を続けていると、 一度や二度は経験する出来事です。ボタンの色を変えただけのつもりが、 モバイルビューのナビゲーションが崩れていた。依存ライブラリをアップデートしたら、 フォントのレンダリングが微妙に変わってテキストがはみ出した。 コードレビューでロジックを確認しても、見た目の変化は気づきにくいものです。 こうした「見た目のバグ」を自動で検出するのがビジュアルリグレッションテストです。

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

ビジュアルリグレッションテスト(Visual Regression Testing)とは、UIのスクリーンショットを自動撮影し、前回の正解画像と比較することで視覚的な差分を検出するテスト手法です。 「リグレッション(regression)」は「後退・退行」を意味し、コードの変更によって以前は正しく表示されていたUIが壊れる現象を指します。

通常のユニットテストはコードのロジック(関数の戻り値・状態変化)を検証するもので、 「見た目が崩れているか」は判断できません。 E2Eテストも操作のフローが正しく機能するかを確認するものです。 ビジュアルリグレッションテストは、その両方が「正しく動いている」状態でも発生する視覚的な崩れだけを専門に検出します。

適用対象は、Webアプリのページ全体から、ボタン・カード・フォームといったUIコンポーネント単位まで幅広く対応できます。 特に、複数のページやコンポーネントが存在するプロダクトで、デザインシステムの変更を安全に反映したい場合に力を発揮します。

仕組み — ベースライン画像とのピクセル比較

ビジュアルリグレッションテストの基本的な流れは次のとおりです。

  1. ベースライン撮影 — 「正しい状態」のUIをヘッドレスブラウザ(Chromiumなど)でスクリーンショット撮影し、「正解画像(ベースライン)」として保存する
  2. テスト実行 — コード変更後に同じページ・コンポーネントを再撮影する
  3. ピクセル比較 — ベースラインと新しいスクリーンショットを重ね合わせ、ピクセル単位で差分を計算する
  4. 差分レポート — 差分が許容しきい値を超えた場合、差分を赤く強調したレポート画像を生成してテスト失敗とする

差分の計算にはピクセルマッチング(PixelMatch)と呼ばれるアルゴリズムが使われることが多く、 2枚の画像の対応するピクセルの色を数値比較します。 差分ピクセルの割合を「差分率」として算出し、設定したしきい値(例: 0.5%)を超えるとテスト失敗と判断します。

主要ツール比較

ビジュアルリグレッションテストのツールは、大きく「CI連携を前提とした自動テストフレームワーク」と 「外部クラウドサービス」に分かれます。代表的な5つを比較します。

ツール特徴コストセットアップ難易度
PlaywrightE2Eテストと統合。toHaveScreenshot() でページ・要素単位のスナップショット比較が可能。ローカルに画像を保存無料(OSS)低(既存E2E環境があれば追加数行)
Storybook + ChromaticStorybookのコンポーネントカタログと連携。クラウド上でレビュー・承認フローを管理できる。UIレビューの専用ダッシュボードが強力無料枠あり(5,000スナップショット/月)、超過は有料中(Storybookのセットアップが必要)
Percy(BrowserStack)複数ブラウザ・解像度での比較に強い。クラウド側で差分を表示・承認。CI統合がシンプル無料枠あり(5,000スナップショット/月)、超過は有料中(SDKとAPIキーの設定が必要)
BackstopJSJSONで設定ファイルを書いてURL・セレクタを指定。Dockerで環境を固定できる。OSSで完結無料(OSS)中(設定ファイルの記述が必要)
手動比較スクリーンショットを2枚並べて目視確認。デザインレビューのスポットチェックや、CI未整備の段階で有効無料最低(ツール不要)

どれを選ぶべきか — チーム規模とCI環境で分岐

ツール選択は「チーム規模」「CI環境の有無」「コンポーネント管理の方法」の3軸で考えるのが実用的です。

  • 個人・小規模チーム・OSS完結したい場合: すでにPlaywrightのE2Eテストがあるなら、toHaveScreenshot() を追加するだけで始められます。 BackstopJSはE2Eテストを持たないプロジェクトでも使えるOSSの選択肢です。
  • Storybookでコンポーネント管理している場合: Chromaticとの連携が最もスムーズです。Storybookの各ストーリーが自動的にテスト対象になります。
  • 複数ブラウザ・デバイスをカバーしたい場合: PercyがChrome・Firefox・Safariのスナップショット比較を標準サポートしています。
  • クラウドサービスのコストを避けたい場合: Playwright + Dockerのローカル比較で完全OSSで構築できます。 ただしベースライン画像の更新・レビューフローは自分で設計する必要があります。

実践的なアドバイス

最初から完璧なCI統合を目指す必要はありません。 まずPlaywrightの toHaveScreenshot() を重要なページ3〜5箇所に追加して運用感をつかんでから、 段階的に対象を広げるアプローチが挫折しにくいです。

手動比較が有効なケース — 画像差分ツールの活用

CIを整備する前の段階、あるいはデザインレビューのスポットチェックでは、 スクリーンショットを2枚用意して人の目で比較する方法が現実的な選択肢です。 ただし、人の目での比較には限界があります。 1〜2ピクセルのずれや、薄い色の微妙な差は見落としやすく、 複数ページを繰り返し確認すると疲労が蓄積します。

そのような場面では、画像差分比較ツールが役立ちます。 「変更前」と「変更後」の2枚のスクリーンショットをアップロードするだけで、 差分のあるピクセルを赤く強調したオーバーレイ画像を生成します。 ブラウザ内だけで処理されるため、社内の未公開UIや機密情報を含む画面でも安心して使えます。 また、コードの差分はテキストベースで確認したい場合はテキスト差分比較ツールが同様に役立ちます。

しきい値の考え方 — 偽陽性との戦い

ビジュアルリグレッションテストを運用する上で最も頭を悩ませるのが偽陽性です。 「意図的に変えていないのに差分として検出される」現象で、これが多いと「また誤検知か」という チームの信頼低下につながります。

主な偽陽性の原因は3つあります。

  • アンチエイリアス:文字・曲線の端のピクセルは、OSや画面解像度によって微妙に異なります。 CI環境と開発環境でOSが違うだけで発生します。
  • JPEG圧縮ノイズ:JPEG形式で保存するたびに微小な色差が生じます。スクリーンショットはPNGで統一するのが原則です。
  • フォント・レンダリングのゆらぎ:同じフォントでもOSバージョンや描画エンジンの違いでサブピクセル単位のずれが発生します。

対処の基本はしきい値の設定です。 差分率が0.5〜2%程度なら「許容範囲」とみなしてテストを通過させることで、 ノイズレベルの偽陽性を排除できます。 しきい値を高くしすぎると本当のバグを見逃すため、実際の偽陽性率を観察しながら0.1〜2%の範囲で調整します。 また、Dockerを使ってCI環境のOS・ブラウザバージョンを固定することも、偽陽性削減に大きく効きます。

注意

しきい値を高くしすぎると、小さな崩れを見逃すリスクがあります。 特に「ボタンのテキストが1行から2行になった」「アイコンが2px右にずれた」のような変化は、 差分率としては小さくても視覚的影響は大きいことがあります。 定期的に手動でサンプル確認することで、しきい値の適切さを検証してください。

まとめ

  • ビジュアルリグレッションテストはスクリーンショットをベースライン画像と比較して視覚的な差分を自動検出するテスト手法
  • ユニットテスト・E2Eテストでは発見できない「見た目のバグ」に特化している
  • 主要ツールは Playwright(既存E2E環境に追加しやすい)・Storybook+Chromatic(コンポーネント管理と統合)・Percy(マルチブラウザ対応)・BackstopJS(完全OSS)
  • ツール選択は「チーム規模・CI環境・コンポーネント管理方法」の3軸で判断する
  • 偽陽性の主な原因はアンチエイリアス・JPEG圧縮ノイズ・フォントのゆらぎ。しきい値設定とDocker環境固定で対処する
  • CI統合前や、デザインレビューのスポットチェックでは画像差分比較ツールを使った手動比較が有効
  • まず重要な3〜5ページにPlaywrightのスナップショットテストを追加して運用感をつかむところから始めるのがおすすめ

よくある質問

ビジュアルリグレッションテストとは何ですか?

UIの見た目が意図せず変わっていないかを自動的に検出するテスト手法です。テスト実行時のスクリーンショットを「正解画像(ベースライン)」と比較し、ピクセル単位で差分を検出します。CSSや依存ライブラリの変更が思わぬ場所のレイアウトを崩していないか、コードレビューだけでは気づきにくい視覚的なバグを発見するのに役立ちます。

ユニットテストやE2Eテストと何が違いますか?

ユニットテストはロジック(関数の戻り値・状態変化)を検証し、E2Eテストはユーザー操作のフローが正しく動くかを確認します。ビジュアルリグレッションテストはその両方が「正しく動いている」状態でも起きる「見た目の崩れ」を検出します。たとえばボタンが正しくクリックできても、フォントが変わってテキストがはみ出していた——というようなバグは、ビジュアルリグレッションテストでしか自動検出できません。

ベースライン画像はどのように管理しますか?

ほとんどのツールでは、初回実行時に自動生成されたスクリーンショットがベースラインになります。その後の変更でUIが崩れた場合は差分として検出され、意図的なデザイン変更の場合はベースラインを手動で更新(「承認」)します。ベースライン画像はGitリポジトリに含めてバージョン管理するのが一般的ですが、画像ファイルが増えてリポジトリが肥大化する点は注意が必要です。

アンチエイリアスやJPEG圧縮による偽陽性はどう対処しますか?

ビジュアルリグレッションテストでよくある問題が「意図的に変えていないのに差分として検出される」偽陽性です。主な原因は3つ——アンチエイリアス(文字・曲線の端のピクセルがOSや解像度で微妙に変わる)、JPEG圧縮ノイズ(保存のたびに微小な色差が生じる)、レンダリングのタイミングによるフォント差です。対処法は、比較しきい値を1〜5%程度に設定してノイズを許容すること、PNGで保存すること、ヘッドレスブラウザの環境を固定(同一OSとフォント)することです。

Playwright、Storybook+Chromatic、Percy、BackstopJSはどれを選べばよいですか?

既存のPlaywrightのE2Eテスト環境があるならPlaywrightのビジュアル比較機能(toHaveScreenshot)が最も導入コストが低く、コンポーネント単位のスナップショット管理が必要ならStorybook+Chromaticが適しています。チームが大きくレビューフローを整備したい場合はPercyやChromatic(有料)が強力ですが、月額コストが発生します。OSSで完結させたい個人・小規模チームにはBackstopJSが選択肢になります。

手動でスクリーンショットを比較する方法はありますか?

あります。CI環境の整備が難しい段階や、デザインレビューのスポットチェックでは、スクリーンショットを2枚並べて人の目で確認する方法が現実的です。ただし人の目での比較は、細かい1〜2ピクセルのずれを見落としやすく、複数ページを繰り返し確認するのは疲労が蓄積します。そのような場面では、2枚の画像をアップロードするとピクセル単位の差分を自動強調表示してくれる画像差分比較ツール(/tools/image-diff)を補助的に使うと、人の目とツールの組み合わせで効率よく確認できます。

ビジュアルリグレッションテストをCIに組み込む方法を教えてください。

GitHub ActionsやCircle CIなどのCIサービスで、PRが作成されるたびにヘッドレスブラウザでスクリーンショットを撮影し、ベースラインと比較するステップを追加します。差分がしきい値を超えた場合にテストを失敗させてマージをブロックする設定が一般的です。PlaywrightやBackstopJSはDockerイメージが公式提供されており、環境差異による偽陽性を防ぎやすくなっています。外部サービス(Percy・Chromatic)を使う場合はAPIキーをシークレットに登録するだけで連携が完了します。

画像差分比較ツールに貼り付けた画像はサーバーに送信されますか?

送信されません。ぱんだツールズの画像差分比較ツール(/tools/image-diff)は、すべての処理をブラウザ内のJavaScriptで完結させています。アップロードした2枚の画像はサーバーに一切送られず、ブラウザのメモリ上でのみ処理されます。社内のUIデザインや未公開の画面のスクリーンショットを比較する場合にも、安心して使えます。

この記事で紹介したツール