STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

Visual regression testingを導入してみた

はじめに

この記事はSTORES Advent Calendar 2023 19日目の記事です。

こんにちは、 STORES 予約 でエンジニアをしている@tontokoです。 STORES 予約 の開発チームでは月に1回、コードクリーニングタイムと呼ばれる日を設けています。

これは普段なかなか手を付けるタイミングが無かった技術負債や、重要ながら後回しにされているタスクなどを片付けることを目的にしています。 当日は緊急度の高いものを除き普段のプロダクト開発の手を休め、内部品質の向上に集中します。

自分は前回のコードクリーニングタイムに、ビジュアルリグレッションテスト(VRT)をフロントエンドリポジトリに導入しました。

導入の経緯

STORES 予約 ではバックエンドのテストに比べると、フロントエンドはまだまだテストの数が少ないです。

ライブラリのアップデートなどの全体に影響する変更の際に、もっとテストが書かれていればある程度安心してリリースできるのに…ということがありました。 しかし、テストが少ないところからいきなりガッツリとテスト書くことを習慣付けていくのはハードルが高かったりします。

何から始めればコスパ良くテストが厚く書かれている状態に持っていけるかと考え、チーム内でStorybookが活用されていることに着目しました。

Storybookとテスト

STORES 予約 の開発チームでは以下のような形でStorybookを活用しています。 またChromaticを利用しており、PRごとに自動でStorybookがデプロイされるようになっています。

  • STORES では Stand と呼ばれるデザインシステムを運用しており、それに則って実装されたコンポーネントであるStandコンポーネントのUIカタログとして
  • PRレビュー、またはデザイナーさんとのUIレビューの際に、ChromaticにデプロイされたStorybookで確認してもらう

Chromatic

このように活用されている中でStoryに対してテストを書くことで、以下のメリットがあると感じました。

  • propsやmswを利用したAPIのモックはすでにStoryに準備されているため、二度手間にならない
  • VRTに関しては、普段通りStoryを書くだけでテスト対象になる

Storybookでテストを行う際はさまざまなアドオンが出ているので、比較的導入はかんたんそうです。

storybook.js.org

またリグレッションテストについては STORES 予約 でも使用しているChromaticを使用する他にも、Storybookのスクショを撮ってくれるStorycap、その画像の差分をテストしてくれるReg-suitというツールがあります。

storybook.js.org

github.com

github.com

今回どんなテストを追加すべきか

フロントエンドのユニットテストとしては、このような方法があります。

  • リグレッションテスト
    • VRT (今回導入したもの)
    • スナップショットテスト
  • 機能テスト
    • クリックするとどうなるかなどをテストする、インタラクションテスト

またWebアクセシビリティを担保するアクセシビリティテストと呼ばれるものもあるようです。

スナップショットテストについては経験上、クラスなどが変わってもそれがUIとして正しいかを見分けるのが難しく、毎回test -uを叩いて更新するだけになり形骸化してしまう懸念がありました。 またインタラクションテストは1日で追加できる範囲には限度があるので、長い目でテストを足していく必要があります。

そこでコードクリーニングタイムの1日で何ができるかを考え、VRTを導入することにしました。

VRTのツールの選定

VRT用のツールとしては上でも書きましたが、以下の候補がありました。

  • Chromatic
  • Storycap + Reg-suit

Chromaticはすでに使用しているためお手軽な選択肢でしたが、規模によってはそれなりの料金になります。 今回は試しに運用してみるというニュアンスもあったので、スクリーンショット保管用のS3の料金程度で済むStorycap + Reg-suitの構成を取りました。

運用してみて

導入方法は公式リポジトリや詳しく書かれている記事があるので割愛します。

導入後にPRをオープンすると、master(main)とのスクリーンショットの差分がレポートと共に飛んでくるようになります。

実際に導入してみて、なかなか難しい点もありました。

何も変更していないのに差分が出てしまうことがある

Storycapはただスクリーンショットを撮るだけなので、場合によって何も変更していないはずでも差分が出てしまうことがあります。

具体的には以下の理由が多かったです。

  • cssでアニメーションが設定されていた
  • APIをモックするmswのレスポンスの遅延が無限(infinite)になっており、Storycapがいつキャプチャすれば良いか分からずタイムアウトする
  • iframeを読み込んでいたので、タイミングによって差分が出た

これらを放置しておくと「どうせ関係ない差分なので見なくても良いか…」となってしまい意味が無くなってしまいます。 どうしても原因を潰せない場合は思い切ってskipし、ノイズを減らしていくことの方が重要だと感じています。

個別の具体的な対処法についてはこちらの記事などを参考にさせていただきました。

zenn.dev

CIの実行に時間がかかってしまう

Storyが増えてくると、Storybookのbuildやstorycapの撮影に時間がかかるようになってきます。

Storycapに関してはcli引数に--shardを渡すことで並列化させることができるので、Story数に合わせて適宜並列で動かすようにしています。

Storybook自体のbuild時間についてはもう少し短くならないかと思ってはいるものの、まだ模索中です。

まとめ

以上、VRTの導入から運用してみてを書いてみました。

まだ導入して日が浅いですが、次にUIに影響するライブラリをアップデートする際などは活躍してくれそうです。 また、今回導入したVRTでは表示についてしかチェックできないため、別途インタラクションテストも拡充し、コンポーネントの動作もテストで担保していく必要がありそうです。

今後VRTを安定化させつつ他の種類のテストも厚くしていくことで、より安心して開発できる環境を作っていきたいと考えています。