💪

デザイナーでも出来る!Visual Regression Test 導入

2022/12/25に公開

はじめに

「デザイナーでも出来る!」記事シリーズです。
私が現在担当している事業サービスでは、Next.js + React + TypeScript を用いてフロントエンドの開発を行っています。
今回は、その課題解決の手段として Visual Regression Test(VRT) を導入したのですが、その経緯や流れについてご紹介できればと思います。
(そして、名前はカッコいいけど長いので、以下できるだけ VRT と呼びます。)

よくあるVRT紹介記事 と違う点としては、
Webデザイナー職だけど導入できた / 事業サービスの課題・導入経緯の詳細アリ というところです。

想定する対象者

  • フロントエンド に興味のあるデザイナー
  • VRT に興味のあるフロントエンドエンジニア
  • Storybookを用いてVRTの導入 を検討されている方

自身の担当事業サービス の5つの課題

1. リリース前後に 表示崩れ と 500エラー に気付けなかった

修正リリース後、しばらく日が経ってから、該当URLの特定のコンテンツが表示できず、
500エラーの状態になっていることが発覚し、少額の利益損失に。

  • もちろん STG/本番環境 で表示検証を行なった上でのリリースでしたが、
    確認ページ数が多く目視確認(人の目)しか検証方法がなく、ミスが起こりやすい状況だった。
  • 修正前後のUI表示差分を検知する仕組み をこの時点では 導入できていなかった。
  • 500エラーを検知する仕組み については導入済みだったが、バグでうまく機能していなかった。
    • こちらはバグ修正し、その後 ちゃんと検知されるようになりました。
    • 逆に、大きな利益損失を出してしまう前に気付けたこと は 不幸中の幸い だったかも。

2. 担当事業メンバーの異動

ちょうど 社内の体制 が変わり始める前のタイミングで、上記のエラーが発生。

  • 社内の体制が変わり、今後は人の異動が前提 となる中で、事業ドメインに詳しいメンバーがいなくても、誰が入ってもしっかり表示検証を担保できる仕組みが必要に。
    • そして、最小構成メンバーで事業を回していける土台づくりが必要。

3. 担当事業サービス の優先度低下

社内の他サービス の優先度が上がり、担当事業サービス の優先度は下がり、開発はストップの状態に。

  • 開発がストップしたので、リリースが無ければ何も変更がないので問題なさそうだが、
    次回リリース時に不安を大きく抱えたままリリース作業をすることになってしまう。
    • 優先度が低くなった事業だからこそ、事前に不用意なエラーを防ぐ仕組みづくりをしておきたい。

4. 表示検証の工数増大

UI修正に対する表示 が担保できているか確認する手段が 目視確認 しかない

  • 結局、開発ストップ後も 表記修正などの細々したリリースが必要で、毎回たっぷり工数をかけて触ったファイルに紐付く全ページを、目視確認で検証してリリースを進めることに。
    • 表示検証の工数 を仕組みで効率化して削減し、他に集中すべきタスクに工数をかけられるようにしたい。

5. 担当事業サービス ではVRTが導入されていない

社内の他サービス では既に Storybook や VRT が導入されていたのに、担当事業サービス は同じような技術スタックなのに導入されていなかった。

  • え? じゃあ入れよう、となった。
  • 既に 社内の成功事例うまく運用に乗っている設定がある状態だったので、同様に展開。
    • ただ、この事業独自の仕様はあるので、そこは合わせる形で。
  • VRT導入による解決やメリット を事業側に伝え、工数を確保して導入を進めることに。
    • この辺り、実際にエラーによって事業に損失が出ていたからこそ、仕組みを導入しよう、という流れは早かった。

課題解決の手段

  • Visual Regression Test(VRT)

Visual Regression Test(VRT) とは?

  • 画像回帰テスト のことです。
    • 各単語を翻訳:Visual(視覚) / Regression(回帰) / Test(テスト)
  • 要するに、コード変更前後のUIのスナップショットを比較し、崩れていないか差分を確認できるテスト
    • スナップショットとは、ある時点でのUIを保存したもの のことですね。

主に使用したライブラリ

1. Storybook

https://storybook.js.org/

概要/用途

  • 今やフロントエンド で デファクトの、UIカタログツールです。
  • 各UIコンポーネント に対する Storyファイル を作成し、スナップショットの対象とします。
    • 画像の比較は、このStoryファイルが対象になりますので、VRTの機能だけ を導入しても Storyファイル が用意できていなければVRTできません。
    • また今回、 VRT導入を目的とする、Storybookの導入が軸なので、不要な option追加はナシ。

2. Storycap

https://github.com/reg-viz/storycap

概要/用途

  • Storybook からスナップショットを生成するためのツールです。
    • reg-suit と作者が同じです。
    • ブラウザ操作ツール の Puppeteer も一緒に追加しないと動かないので入れます。
    • Storyファイルのキャプチャ方法(タイミングやサイズなど)を制御したいので、
      Managed mode で使用します。

3. reg-suit

https://github.com/reg-viz/reg-suit

概要/用途

  • 汎用的な VRT の枠組みを提供するツールです。
    • storycap と作者が同じです。
    • 比較元、比較先の画像を検証にかけ、差分の有無を検知してくれます。
    • 検証の結果 を分かりやすい形式でレポートしてくれます。

VRT導入手順

前置きが長くなりましたが、ここから導入手順です。

  1. Storybook の導入
  2. Storyファイル の作成
  3. storycap の導入
  4. reg-suit の導入
  5. レポートストレージの設置 と CI/CDの設定
  6. VRT の動作検証

Storybook の導入

  • 以下コマンドで、Storybook を導入。
$ npx storybook init
~

Field 'browser' doesn't contain a valid alias configration
  • いきなりエラーでコケました。。
  • まずは Storybookを導入する前に、エラー解消 が必要でした。
    • 既存プロダクトに追加する際には、こういうのあるあるな気がします。
    • プロダクトを保守するという意味で、コードを見返す良い機会になりました。
  • 以下の点の修正が必要でした。
    • tsconfig.json で使用している エイリアスのパス が間違っているコンポーネントがある
    • import するファイルの 参照先 が間違っている
  • エラー修正後、再度コマンドを実行し、無事 Storybook を導入できました。

main.js と preview.js の調整

  • コマンド実行後、自動で新たにファイル追加されるので、調整します。
  • preview.js は、アプリ側と同じ構成 になるようにします。

Storyファイル の作成

  • 全UIコンポーネント に対する Storyファイルを作成します。
    • 今回は最小構成で導入のため、1ファイルだけ用意。
    • フォーマットは CSF3 で作成します。
  • 例)Header.tsx に対して、Header.stories.tsx を作成します。
Header.stories.tsx
import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'
import { spViewport } from '@stories/options/viewports'
import { Header } from '@components/sp/default/shared/Header'

type Story = ComponentStoryObj<typeof Header>

const component = {
  component: Header,
  parameters: { ...spViewport },
}

export default component as ComponentMeta<typeof Header>

export const Mobile: Story = {}
  • viewports.ts というファイルを作成しspViewportを参照することで、
    スマホ幅でのスナップショット が可能になります。
viewports.ts
export const Viewports = {
  iphone6: {
    width: 375,
    height: 667,
  },
}

export const spViewport = {
  viewport: {
    defaultViewport: 'iphone6',
  },
  screenshot: {
    viewports: {
      iphone6: Viewports.iphone6,
    },
  },
}
  • 以下コマンド実行で Storybookが立ち上がり、作成したstoryファイル を確認できます。
    • 通常 6006番 で立ち上がりますが、弊社では複数事業にStorybookを入れているので、区別しやすいように番号を変更しています。
$ yarn storybook

http://localhost:6006/

storycap の導入

  • 以下コマンドで、storycap と puppeteer を導入。
$ yarn add -D storycap puppeteer
  • package.json に scripts の定義をします。

reg-suit の導入

  • 以下コマンドで、reg-suit を導入。
$ yarn add -D reg-suit
  • reg-suit の初期設定をする
$ yarn reg-suit init
  • コマンド実行すると対話形式が始まり、詳細な設定を選択できます。
  • 以下の、必要なplugin を選択
// reg-suitの結果 を Gitlabリポジトリ に通知する
// → Github を使用している場合は、reg-notify-github-plugin を選択
◉ reg-notify-gitlab-plugin

// スナップショット イメージを取得して AWSのS3 に発行する
◉ reg-publish-s3-plugin

// 指定された値でスナップショット キーを決定する
◉ reg-simple-keygen-plugin

~
  • S3のバケットを作成済みの場合、バケット名を入力します
~

// 
? Existing bucket name
●●
  • regconfig.json が自動で追加されます。
  • package.json に scripts: "regression" の定義をします。

レポートストレージの設置 と CI/CDへの組み込み

  • 上記までの設定完了後、レポートストレージの設置 と CI/CDへの組み込みについては、エンジニアに協力してもらいました。
    • CI環境は Gitlab CI/CD を利用
    • 本来は、ローカル環境 でVRTの動作検証を行ってからCI/CDに乗せる流れが良いのですが、既にある社内の成功事例を同様に展開 というところと、AWSのAccessKey や Secretkey が万が一にも流出すると困るというところで、最初から CI/CD に組み込んでもらう流れになりました。

VRT の動作検証

  • ここまでで、VRTの準備が整いました。
  • mainブランチから新規ブランチを切り、作成したStoryファイルに対するUIコンポーネントで、わざと表示差分が出るようなMR を作成します。
  • すると、MRにコメントが追加されます。実際の表示はこんな感じです。
  • そして、実際のreport表示 はこんな感じです。
  • VRTの動作、問題なさそうです。
  • 以上で、最小構成でのVRTの導入 が完了しました!

はじめてのVRT導入で考えたこと

社内の他サービス では既に VRT が導入されており、その内容を浅く知っていたのですが、
自分がイチから導入するというところで、まずどう進めていくのが良いのかを考えました。

考えた道筋(ゴールまでの意識)

  • 小さなゴールを置くこと。
  • できそうなところから着手すること。
  • VRT導入済み の事業サービス を参考にすること。
  • 自分が手に負えないところについては、エンジニアと連携すること。

スケジュール感(工数)について
1ヶ月ほどで完了できたのですが、他タスクも並行しながらだったのであまり参考にならないと思います。

VRT導入後 のワークフロー

既存UIコンポーネント変更の場合

  1. 事業サービス の運用に伴う仕様変更などにより、対象のUIコンポーネントに変更が発生する
  2. (対象のUIコンポーネント に対する Storyファイル が作成済み)
  3. 修正MR作成後、MRに表示される VRT の コメント と レポート を確認
  4. UI変更内容 を担保しながら、安心感を持ちつつリリース

新規UIコンポーネント作成の場合

  1. 事業サービス の運用に伴う仕様変更などにより、新規UIコンポーネント作成が発生する
  2. 対象のUIコンポーネント に対する Storyファイル を作成し、リリース
  3. 次回 UIコンポーネント修正リリース時に、安心感を持ちつつリリース

残った課題 と 今後のトライ

1. タスク工数 が確保できないことによる Storyファイルのカバレッジ担保不足

  • 最小構成で導入したものの、全ての UIコンポーネントに対するstoryファイルの担保がまだできておらず、VRT機能だけ がプロダクトに入ったような状態に。。

→ こちらは、今後しっかりと保守のための工数を確保し、Storyファイルのカバレッジを広げて VRTが機能するようにしていく予定です。

2. 他メンバーへの VRT関連スキル の啓蒙/継承不足

  • Storyファイルの作成 や VRTの設定調整できるスキル を持ったメンバーが少なく、他のメインタスクで工数もあまり割けない状況のため、スキルの啓蒙/継承 が不十分。

→ こちらは、VRTに関するWikiを展開し、他のメンバーでも運用できるようにしていく予定です。

3. report結果 で意図せず差分とみなされるコンポーネントがある

  • 意図せず差分として出力されるコンポーネントが存在することにより、毎回差分としてreportされてしまう。

→ こちらは、Storyファイル や VRTの設定数値 などを調整し、改善していく予定です。

まとめ

いかがだったでしょうか?
何かお役に立つ情報になっていれば嬉しいです。
ぜひVRTを導入して、UIが担保できている堅牢なプロダクトにしていきましょう。

Discussion