Visual Regression Testをサポートするreg-actionsをリリースした
2023-11-18
Visual Regression Test(以下VRT)をやろうと思うと画像をどこに保存するかを検討する必要がでてくるケースがある。
(web アプリケーションのVRTを前提とすると)多くの場合、テキスト形式である*.snapとは異なり、画像取得時のOSやfont、ブラウザのversionなどにより差分がでやすくなってしまう。そのため画像はCIなど環境を極力そろえた状態で取得し、S3などに上げVRT対象の画像を管理するケースがみられる。
今回はこのフロー・管理の簡略化を目指しactionsを作成・リリースした。
目次
INFO
この記事はZennに記載した記事の Clone となっている。
成果物
repositoryは以下。yamlに後述するstepを記述すれば使用できる。
セットアップ
最小の記述は以下となる。これで./images以下の画像に対してVRTを行ってくれる。VRTに必要な画像管理はactionsが受け持ち、PRごとにレポートをコメントする。
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: reg-viz/reg-actions@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
image-directory-path: "./images"
サンプル
簡単な動作は以下のrepositoryで確認ができる。
現状はPRとJob Summaryの両方にコメントされるが、将来的にはdisableにできるフラグも用意しておくつもり。
以下のサンプルは最小限のセットアップにおいて画像に差分を発生させてみたサンプルだ。
PRコメント
JobSummary
どのように動作するか
以下の手順で動作する。大前提として画像はすべてartifactとしてgithubにアップロードする。
actionsに渡される情報から比較対象とするcommitを求め、そこからrunIdを取得するrunIdから比較対象となるartifactを取得する- 画像を比較し、結果を
artifactとしてアップロードする - 差分がある場合、指定ブランチにコメントのための差分画像を
pushする(disable-branchがfalseの場合) - コメントする
1. actionsに渡される情報から比較対象とするcommitを求め、そこからrunIdを取得する
github actionsではpに配置されたjsonを読むことでpull_requestの情報などを取得できる。
これをもとにbaseブランチをもとめ、比較対象とすべきcommitを算出する。
2. runIdから比較対象となるartifactを取得する
1でcommitが算出されたらrunIdを取得し、そこに紐付くartifactをyamlに設定されたartifact-nameをもとに download する。
3. 画像比較を行い、結果をartifactとしてアップロードする
2で download した画像とyamlに設定されたimage-directory-pathをreg-viz/reg-cliのcompareを用いて比較し、差分画像とレポートを生成する。その後artifactとして upload する。
抜粋だが、upload は以下のように行える。
import * as artifact from '@actions/artifact';
const client = artifact.create();
await client.uploadArtifact(artifactName, files, workspace())
4. 差分がある場合、指定ブランチにコメントのための差分画像をpushする(disable-branchがfalseの場合)
以前から PR のコメントに直接画像を貼り付けたいと考えていたが、その場合画像の保存先が問題となる。S3などをわざわざ用意したくない。というのがこのactionのモチベーションでもあるためだ。しかし、artifactはzipであるため、その中に含まれる画像は直接コメントに貼り付けることはできない。
そのため、本actionではs0/git-publish-subdir-actionを参考にrepositoryのブランチを間借りしてしまう案を採用した。 つまり画像に差分が発生した場合はbranchoptionで指定したbranchに差分画像をpushし、そのURLをコメントに貼り付ける。これによりprivate repositoryでも使用が可能となる。
この機能は個人的には気に入っているものの、「勝手に push されたくない...」というケースもあるように思う。(なんなら自分で作ったものでなければ自分もそう思うかもしれない。)その場合disable-branchをtrueにしておけばpushはされなくなる。
ただし、その場合画像がコメントに貼り付けられなくなるので、差分を確認するには自分でartifactを 手元にdownload したり、レポートを自分で upload する必要がでてくるかもしれない。(すでにそのような使い方をしているユーザもいるようだ。)
このようなケースのためにgh extensionを用意し、コマンド一発でreg-cliのレポートが開くような工夫をしてもいいのかな。と感じている。
5. コメントする
ここまでくれば、あとはコメントするだけだ。最近Job Summariesにもmarkdownを投稿できることを知ったので、こちらにもレポートが投稿されるようにした。 これも手軽に行える。
import { summary } from '@actions/core';
await summary.addRaw(`# Hoge`).write();
Tips
画像の取得について
storybookと合わせてVRTを行っている方も多い認識だが、その場合はreg-viz/storycapを使用すれば簡単にstoryごとの画像が取得できる。
また、test-runnerが入っている場合は以下のようにpostRenderで取得しても良い。
const { resolve } = require('path');
const { writeFile } = require('fs').promises;
module.exports = {
async postRender(page, context) {
const image = await page.screenshot();
await writeFile(resolve([YOUR_DIR], `${context.id}.png`), image);
},
};
比較対象の制御について
デフォルトの挙動としては前述したようにPRのマージ先から自動的に算出するが、これを固定したり自分で割り出したい場合はtarget-hashoption を使用することで指定できる。また、以下のようにgithub scriptを使用して算出も可能だ。
- uses: actions/github-script@v5
id: target
with:
result-encoding: string
script: |
return (Math.random() > 0.5) ? "59b7802" : "34f93ed"
- uses: reg-viz/reg-actions@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
image-directory-path: "./images"
target-hash: "${{ steps.target.outputs.result }}"
一つのPRで複数のVRTを行う
以下のようにartifact-nameをユニークに設定することで1つのPRで複数のVRTを行うことが可能となる。弊社もe2e用とinteraction用で分けてVRTを行っているケースがある。
- e2e用
- uses: reg-viz/reg-actions@v2
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
image-directory-path: 'e2e_images'
artifact-name: 'e2e'
- interaction用
- uses: reg-viz/reg-actions@v2
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
image-directory-path: 'interaction_images'
artifact-name: 'interaction'
TODO
まだいくつかタスクは積んでいてちょっとずつ作業はしていくつもりだ。主に以下のようなことを考えている。
reg-viz/reg-cliのwasm化webpの対応retention-daysoption の追加gh extensionの用意
やはりNode.jsでこういったツールを書くのはセキュリティ面で担保するのが難しいな。とたびたび思う。今でこそPermissionsがあるが、だったらいっそのことwasm化してやったほうがいいのではないかと考えている。
また、画像サイズを小さくすることにはメリットがあるのでwasm化と合わせwebpにも対応できたら良いなと考えている。
現状の仕組みではbranchの画像が増えていってしまうのでなるべく早くretention-daysは用意するつもり。
まとめ
reg-actionsを紹介した。社内で使用しはじめているが、なかなか快適で、TODOにあるタスクを粛々と進めていきたい。
以上。

