Visual Regression Testはじめました
以前から始めてみたかったんですが、機会があったのでようやくはじめられました。
学びあるいはつまづきがあったので、メモしておきます。
Visual Regression Testとは
フロントエンドテストのひとつ。
実際にブラウザー上でフロントエンドを表示し、そのスクリーンショットを正しいとされるスクリーンショットと比較することで検証する。
フロントエンドのコンポーネントテストではクラスやIdが正しく付与されているかをチェックするが、描画崩れは検知できない。実際に描画することで描画崩れも検知できるすぐれもの。
技術調査
導入にあたり、いくつかの技術を検証しました。ぶっちゃけ導入自体はそんなに難しくなく、どちらかというと導入後の運用に課題があるなと感じました。が、もったいないのでメモしておきます。
まず、技術の要素として
- スクリーンショットを取得する
- スクリーンショットの差異を検証する
という2点が挙げられます。
それぞれはそんなに難しくないので、好きな技術を組み合わせるとよいと思います。
撮る・比較する
playwright
playwright自体はJavaやPythonにも対応しているのですが、ライブラリがJavaScriptにしか対応していないのでJSのみで利用できます。
@playwright/test
というライブラリがあり、顧客が本当に欲しかったものとはこれだったのだという気持ちになります。唯一、スクショの撮影から比較、画像の更新までをやってくれるやつです。
Jestのスナップショットテストと同様にスクショがなければ新規作成、あれば比較というのをやってくれます。 playwright test
で実行することができます。
気になるところというと、スクショを保存すると実行したプラットフォームの名前が保存画像のファイル名に付与されてしまうという点でしょうか。ローカルのMacで画像を保存しても、CI/CDはLinuxということはよくあり、CI環境で比較が行われないということが起きそうです。
この問題はissueにも上がっていました。
撮る
Selenium/Selenide
WebDriver系のツールです。対応言語が多いので、好きな言語で書けるのがいいですね。
ページ全体のスクリーンショットを撮るには追加でライブラリが必要だったりするので、その点は注意が必要です。
puppeteer
正直、playwrightとあまり変わらないので、どっちでもよいかなと思ったりします。
Storycap
StorybookのプラグインでStorybook内のコンポーネントを全部撮ってきてくれる便利なやつのようです。CLIツールです。内部ではpuppeteerを使ってスクショを生成しています。
Storybookを使ってコンポーネントを管理しているならけっこうよさそうですね。
私はStorybookを使っていないので、なにも言えないです。
比較する
image-comparison(Java)
Javaのライブラリです。
比較した結果、差分の割合を取得できます。差分は、ピクセル単位ではなくボックス単位かも。正確な割合が知りたい場合には向いてないでしょう。
差分の箇所を赤枠でマークして出力することもできます。
差分の割合の取得、差分の箇所の出力、どちらもVisual Regression Testに必要な機能だと思いますが、両方あるので必要十分というところでしょうか。
blink-diff(JavaScript)
古くてもう更新されていませんが、たぶんしっかり作られていたものだと思います。
こちらも、差分の割合や差分画像を出力することができます。
pixelmatch(JavaScript)
blink-diffなどからインスパイアされたツールです。差分の割合や差異画像を出力できます。
やったこと
Kotlin, Selenide, image-comparisonの組み合わせで構築しました。
End to Endテスト(E2Eテスト)がKotlin, Selenideで作られていて、image-comparisonを追加するだけでOKだったので、E2Eテストに追加する形で構築しました。
想定している運用としては、ローカルで正解画像を出力しておき、CI/CDで検証するという方法です。
やってみて気づいた問題点
実行環境によって出力される画像が違う
Macで出力すると、Retinaサイズの画像が出力され、Linuxで出力すると通常サイズの画像が出力されます。比較するライブラリによってはサイズを縮小して比較してくれるものもあるかもしれませんが、それはそれで微妙に差異が出ると思うので、環境を揃えるべきだなと思います。
さらに、インストールされているフォントによっても出力される見た目が異なるので、そこも注意が必要です。(逆に環境によってフォントが異なることに気づけるかも?)
対策として、CI/CDがLinuxなので、Macで出力するときはDocker上で実行しました。
通信待ちで想定外の画像が撮れる
通信するアプリケーションだと、ロード中のスクリーンショットが撮れてしまって、画像が一致しない、なんてこともあると思います。対策として、通信が完了して想定したとおりのコンポーネントが表示されていることをチェックした上でスクリーンショットを撮るようにしています。
また、アニメーションが画面内に映り込んでいる場合などは他の対策が必要でしょう。
感想
思ったより、問題点が少なくてよかったです。私が導入したプロダクトではすでにEnd to Endテストが用意されていたので、導入も簡単でした。おそらく、イチからやるならCI/CDでブラウザーを動かして、スクリーンショットをどうやって撮るんだ、みたいなことを考えなければならないので、大変だろうなと思います。
以上です。よろしくお願いします。
Discussion