今日はVisual Regression Testの導入の話をします。
いろいろと端折っているのでこのままコピペしても動きません
はじめに
今回はコンポーネント単位でのVRTと、アプリケーションページ単位でのVRTの2種類を導入します。
StoryBookに載せるコンポーネントというのはいわゆる部品というもので、それらを組み合わせて出来上がったページ本体は載っていない想定ですが、アプリケーションのVRTを考えるとやはり出来上がったページ本体のレイアウトに妙な変更が起きていないかを確認したいものです。そこでStoryBookでのVRTとは別にアプリケーションのページを対象としたVRTを行う事で、この課題に対応しようと思いました。
技術選定
巷にはVRTの構成サンプルはStoryBookを利用して各Storyの差分を検出するものが多く流れています。プロジェクトでもStoryBookを利用してコンポーネントカタログを作成する予定のため、同じような構成でいくことにしました。
StoryBook
言わずと知れたUIカタログ作成ツール
StoryCap
各Storyのスクリーンショットを撮影できるStoryBookのアドオン。内部的にpuppeteerを利用しており、Chromeしか対応していない(firefoxも対応したようだがStorycCapはまだっぽい)
クロスブラウザ対応という点でE2EテストツールであるPlaywrightも良さそうだが、今回は時間が限られているため、社内で前例があったStoryCapを採用
reg-cli
画像を比較しHTMLレポートを生成するシンプルなツール
比較画像の取得、レポートの連携をいっぺんにやってくれる reg-suit というツールもあったが、比較画像の特定にキー生成プラグインが必要で、ありもののreg-keygen-git-hash-plugin
では具合が悪かった1ので色々と手動でできる reg-cli
を採用
構成図
CIはGitHub Actionsを使用しています。
作っていく
各種インストール
まずは選定した各種ツールをインストールします。
pnpm add -D storybook storycap puppeteer reg-cli
puppeteer
を動かすにはいくつか依存パッケージが存在するのでそれも入れておきます。
sudo apt-get update && sudo apt-get install -y libgtk-3.0 libgbm-dev libnss3 libatk-bridge2.0-0 libasound2
各種スクリプト
package.json
にVRT関連のスクリプトを追加します
"storybook.build": "storybook build -o storybook-static",
"storycap": "puppeteer browsers install chrome && storycap --outDir .reg/actual --serverCmd 'pnpm dlx http-server --port 7174 storybook-static' http://localhost:7174",
"vrt.components": "reg-cli ./.reg/actual ./.reg/expected ./.reg/diff -R ./.reg/report/index.html",
-
storybook.build
StoryBookを静的ビルドします。デフォルトでstorybook-static
に出力されますが他で指定するパスなので動かないよう明示します。 -
storycap
スクリーンショットを撮影します。StoryBookはどこかにホストしている訳ではないので、開発用サーバで自前起動します。ブラウザのインストールはpuppeteer
とは別途必要なためここで実行します。比較を.reg/actual
と.reg/expected
で行いたいので合うように出力します。 -
vrt.components
スクリーンショットを比較します。レポートを.reg/report/index.html
に出力するよう明示します。
GitHub Actions
まずは pull request
時のVRT本体を作っていきます。
name: ビジュアルリグレッションテスト
on: pull_requst
# 実行内容
jobs:
# jobID
visual_regression_test:
name: ビジュアルリグレッションテスト
runs-on: ubuntu-latest
permissions:
id-token: write # AWS認証のため
contents: read
packages: read
pull-requests: write
# 実行コマンドたち
steps:
# node installとか略
- name: 文字化け対策
run: sudo apt install fonts-ipafont fonts-ipaexfont
- name: Storybookのビルド
run: pnpm storybook.build
- name: snapshotを撮影
run: pnpm storycap
- name: AWS認証
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ap-northeast-1
role-to-assume: ${{ secrets.aws-role-arn }}
- name: mainブランチの画像をダウンロード
run: aws s3 sync s3://${{ vars.snapshot-s3-bucket }}/ ./.reg/expected/
- name: ビジュアルリグレッションテストの実行
id: visual-regression-test
run: pnpm vrt.components
continue-on-error: true # 差分があっても失敗とはマークしない
- name: テスト結果を保存
id: save-report
# VRTが実行された場合のみ保存
if: always() && (steps.visual-regression-test.outcome == 'success' || steps.visual-regression-test.outcome == 'failure')
run: aws s3 sync ./.reg/ s3://${{ vars.report-s3-bucket }}/
# 結果のPR連携 略
StoryCap
でスクリーンショットを撮影する際日本語が文字化けを起こすのでフォントをインストールします
- name: 文字化け対策
run: sudo apt install fonts-ipafont fonts-ipaexfont
先ほど追加したスクリプトを利用してStoryBookの静的ビルドを生成します
- name: Storybookのビルド
run: pnpm storybook.build
先ほど追加したスクリプトを利用してスクリーンショットを撮影します
- name: snapshotを撮影
run: pnpm storycap
S3から画像をDLするのに必要なAWSの認証を済ませてから比較用の画像をDLします
- name: AWS認証
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ap-northeast-1
role-to-assume: ${{ secrets.aws-role-arn }}
- name: mainブランチの画像をダウンロード
run: aws s3 sync s3://${{ vars.snapshot-s3-bucket }}/ ./.reg/expected/
先ほど追加したスクリプトを利用して画像比較&レポートを出力します。ここでは省略していますがこの結果を以ってプルリクエストへコメントする内容を変更するため、差分が出ても失敗とはせずCIを続行させます。
- name: ビジュアルリグレッションテストの実行
id: visual-regression-test
run: pnpm vrt.components
continue-on-error: true # 差分があっても失敗とはマークしない
最後に結果レポートをS3へ保存します
- name: テスト結果を保存
id: save-report
# VRTが実行された場合のみ保存
if: always() && (steps.visual-regression-test.outcome == 'success' || steps.visual-regression-test.outcome == 'failure')
run: aws s3 sync ./.reg/ s3://${{ vars.report-s3-bucket }}/
次に merge
時のイメージの更新を作ります。
name: イメージ更新
on: pull_requst
# 実行内容
jobs:
# jobID
update_images:
name: 正解イメージ更新
runs-on: ubuntu-latest
permissions:
id-token: write # AWS認証のため
contents: read
packages: read
pull-requests: write
# 実行コマンドたち
steps:
# node installとか略
- name: 文字化け対策
run: sudo apt install fonts-ipafont fonts-ipaexfont
- name: Storybookのビルド
run: pnpm storybook.build
- name: snapshotを撮影
run: pnpm storycap
- name: AWS認証
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ap-northeast-1
role-to-assume: ${{ secrets.aws-role-arn }}
- name: スナップショットのアップロード
run: aws s3 sync ./.reg/actual/ s3://${{ vars.snapshot-s3-bucket }}/ --delete
最後のスナップショットのアップロード以外はVRT本体と変わりません
Visual Regression Test 導入その2
-
ブランチを切った元のコミットではなくmainブランチの最新版と比較したい ↩