見出し画像

Visual Regression Test をローカル環境で導入する

CyberZ の Webフロントチームでエンジニアをしている山﨑です。現在 CyberZ Webフロントチームでは、サービスの安全性を向上を目指し、テストの拡充を行なっております。その中で Storybook や storycap, reg-cli を使用した Visual Regression Test の導入を行なったため、その実装例をご紹介したいと思います。
Jest と React Testing Library を用いた Integration Test|CyberZ Developer

Visual Regression Test と やりたいこと

まず、簡単に Visual Regression Test の説明をしたいと思います。Visual Regression Test とは、ある時点での画像の差分を検知し、意図せぬ UI の表示変更が起こっていないかテストするものになります。そのため、現状の UI の画像と何かしら変更を加えた UI の画像を比較し、共通化させているコンポーネント等で、予期せぬ UI 崩れや不具合を起こしていないかを確認するというのが主な使い方になります。
一般的には、GitHub や AWS S3 等と紐付けることで、Pull Request に対して Visual Regression Test を毎度実行し、問題が起こっていないか確認する方法がこのテストの理想形です。ですが、小規模なチームだと少なからず発生する管理コストなどの問題もあるため、実装するハードルは低くないと感じています。一方で、小規模なチームほど細かな UI 崩れや不具合に気付きにくく、Visual Regression Test を導入する事の意味は大きいものになります。そのため、今回の記事では、フロントだけで完結できる簡易的な Visual Regression Test の導入方法を紹介したいと思います。
今回導入しているテスト方法は、GitHub や AWS S3 等で画像の管理をすることができないため、「大きな UI 変更・修正を行う最初の段階で生成した画像」と「UI の変更・修正後に生成した画像」を比較し、差分を確認できる状態を目指します。そのため、テストを行うための流れは以下のようになります。

1. 修正前の画像を生成
2. UI の変更・修正
3. 修正後の画像を生成
4. 画像を比較

Storybook の導入

Install Storybook
Storybook は公式ドキュメント内で導入方法が丁寧に説明されているので、詳細は省きたいと思います。また、バージョンが異なる場合、多少書き方が異なるので、適宜修正を加えていただければと思います。

npx storybook@latest init
// package.json
{
	"scripts": {
		"storybook": "start-storybook -p 6001",
	},
	"devDependencies": {
		"@storybook/react": "6.5.6",
	}
}
// Button.stories.tsx

import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Button from './view';

export default {
  title: 'Button',
  component: Button,
} as ComponentMeta<typeof Button>;

const Template: ComponentStory<typeof Button> = (args) => <Button { ...args } />;

export const Default = Template.bind({});
Default.args = {
};

storycapの導入

https://github.com/reg-viz/storycap
storycap は Storybook で管理している UI カタログから、スクリーンショット画像を生成するためのライブラリになります。そのため、今回行うことは「現状の UI のスクリーンショット画像の生成」と「変更を加えた UI のスクリーンショット画像の生成」を担う事になります。

npm install --save-dev storycap
// package.json
{
	"scripts": {
		"storybook": "start-storybook -p 6001",
		"screenshots": "storycap --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
	},
	"devDependencies": {
		"@storybook/react": "6.5.6",
		"storycap": "4.1.1",
	}
}

screenshot というコマンドで storybook に対してのスクリーンショット画像を生成するように実装を行います。実際に実行してみると以下のように __screenshots__ ファイルが生成され、storybook のスクリーンショット画像が格納されます。

__screenshots__
screenshots画像

storycap が行なっている事は非常にシンプルで、Storybook の立ち上げと、その立ち上がった環境と各コンポーネントに対してスクリーンショットを生成するというものになっています。

テストを行う画像の生成

最初に結論で挙げているように、「大きな UI 変更・修正を行う最初の段階で生成した画像」と「UI の変更・修正後に生成した画像」とを比較することになるので、それぞれの画像を生成できるような環境を構築する必要があります。そのため、生成した画像を格納するファイルを以下のように定義し、実行するコマンドの修正を行います。

// 画像を格納するファイル構成
- __screenshots__
		- comparison   // UI 変更・修正後の画像を格納
		- main         // UI 変更・修正を行う前の画像を格納
// package.json
{
	"scripts": {
		"storybook": "start-storybook -p 6001",
		// "screenshots": "storycap --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
		"vrt-before": "storycap -o ./__screenshots__/main --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
		"vrt-after": "storycap -o ./__screenshots__/comparison --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
	},
}

storycap は -o オプションで生成する画像ファイルの格納位置を指定できるため、修正前と修正後のスクリーンショット画像を生成するコマンドを追加します。実際に実行してみると、それぞれのファイルに対して画像が生成されていることが確認できます。

__screenshots__

ここで生成された main ファイルの画像と comparison ファイルの画像に対して、次に紹介する reg-cli を実行し、差分の比較を行います。

reg-cli の導入

https://github.com/reg-viz/reg-cli
reg-cli は指定された画像同士を比較し、検出した差分に対しての HTML ファイルを生成してくれるライブラリになります。GitHub や AWS S3 と紐づけて Visual Regression Test を行う場合には、reg-suit という reg-cli を包括したライブラリを使用することで実装することができます。

npm install --save-dev reg-cli
// package.json
{
	"scripts": {
		"storybook": "start-storybook -p 6001",
		"vrt-before": "storycap -o ./__screenshots__/main --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
		"vrt-after": "storycap -o ./__screenshots__/comparison --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
		"reg": "reg-cli ./__screenshots__/main/** ./__screenshots__/comparison/** ./__screenshots__/diff -R ./__screenshots__/report.html -I true"
	},
}

reg というコマンドを新たに追加し、reg-cli の実行を行なっています。reg-cli の比較する画像の指定方法は以下のようになっています。

reg-cli 比較元の画像ファイル 比較対象の画像ファイル 生成した比較画像の格納先 比較差分に対しての HTML ファイルの格納先

reg-cli ./__screenshots__/main/**  ./__screenshots__/comparison/** ./vrt/__screenshots__/diff -R ./vrt/report.html -I true

このように、reg-cli に対して4つの指定をしてあげることで、簡単に比較した差分データを生成してくれるようになっています。また、比較差分に対しての HTML ファイルの格納先の中で指定している -R オプションは、差分の HTML ファイルを生成するためのものと、-I オプションは画像の差分が検出された時にエラーを投げないための指定になります。
実際に、UI の表示スタイルを修正し、vrt-after の実行後に reg コマンドを実行すると、以下のように HTML ファイル等が生成されていることがわかります。

__screenshots__
reg-cli

使いやすい形にリファクタリング

修正前に vrt-before を実行、修正後に vrt-after を実行、その後に reg を実行し、生成された HTML ファイルを確認、という流れでも問題なく差分の確認を行うことができます。ですが、少し手間が多いため、リファクタリングを行いたいと思います。

// package.json
{
	"scripts": {
		"storybook": "start-storybook -p 6006",
        "vrt-before": "storycap -o ./__screenshots__/main --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
        "vrt-after": "npm run vrt:screenshot && npm run vrt:reg && open ./__screenshots__/report.html",
        "vrt:screenshot": "storycap -o ./__screenshots__/comparison --serverCmd \\"start-storybook -p 6001\\" <http://localhost:6001>",
        "vrt:reg": "reg-cli ./__screenshots__/main/** ./__screenshots__/comparison/** ./__screenshots__/diff -R ./__screenshots__/report.html -I true"
	},
}

結論、このような形で実装することで、修正前に vrt-before を実行、修正後に vrt-after を実行、とするだけで、差分の確認を行うことができます。

実行順序
1. npm run vrt-before で修正前の画像を生成
2. UI の変更・修正
3. npm run vrt-after で修正後の画像の生成と比較テストを実行
4. 予期せぬ UI 崩れや不具合がないか確認

まとめ

今回の記事では、Visual Regression Test をローカル環境で行える環境構築の方法を紹介しました。今回の実装を通して、Visual Regression Test による UI に対しての安全性の向上を図ることができました。また、本来であれば GitHub や AWS S3 と reg-suit を紐付けた実装がベストなやり方だとと感じますが、フロント内で完結できる上に、実装上の負担もそこまで大きなものではありませんでした。そのため、チーム状況によってはローカルだけで活用する実装でも、問題なくテストとして機能すると感じました。

この記事が気に入ったらサポートをしてみませんか?