【前編】Visual Regression Testing の内製化への道 🚀 〜Chromaticから代替ツールへ〜

こんにちは!カイポケリニューアルの開発推進チームでエンジニアをしている @_kimuson です。

フロントエンド開発において視覚的リグレッションテスト(Visual Regression Testing、以下 VRT)は欠かせない存在です。 私たちのチームでは長らくChromaticを活用してきましたが、プロジェクトの成長に伴い、よりスケーラブルでコスト効率の高いソリューションを模索する必要が出てきました。

本記事は 2 部構成の前編として、内製化の決断に至った背景と代替ツールの検討過程を紹介します。 後編では実際の実装プロセスと移行作業の詳細に焦点を当てる予定です。

内製化の決断 🤔

Chromatic の利点

Chromatic は Storybook をベースにした VRT を提供する SaaS です。 簡単なセットアップで優れた開発者体験と直感的なインターフェースを提供しています。

私たちのチームが特に価値を感じていた点は以下の通りです:

  • 最小限のセットアップのみで Storybook をベースにした VRT を動かすことができる
    • VRT のしきい値も効果的に設定されており、特にチューニングせずとも Flaky(不安定な)テストを最小限に抑えられている
  • わかりやすい差分の表示と、Story 単位での変更承認/拒否の柔軟なワークフロー
  • VRT により、安全にフロントエンドを編集できる点
  • コードレビューの際に変更によって UI がどう変更されるのかが自動でわかる開発者体験
  • VRT に加えて Storybook がホスティングされ、非エンジニアに再現の難しい状態の UI を共有できる点

Chromatic に大いに助けられてきましたが、プロジェクトの規模拡大に伴い課題も見えてきました。

内製化を検討するきっかけ 💰

最大の課題はコストでした。

我々のチームではスナップショットの総数が月あたり約 13 万スナップショットずつ増加しており、検証開始の時点で合計約 70 万スナップショットに達していました。 Chromatic の課金形態はスナップショット数に対する従量課金であり、スナップショットに対して線形に金額が増えていきます。プロジェクト規模に適したコスト構造を考え、内製化を検討するに至りました。

月辺り 13 万スナップショット増加していることからもわかるように、フロントエンドのコードベースと機能拡大に伴って、この費用は今後も増加が予想されます。

そこで、Chromatic の優れた開発体験をできる限り維持しながら、よりコスト効率の高い代替手段を探ることにしました。

代替ツールの検討 🔍

内製化にあたって重要だったのは、Chromatic が提供していた価値をどう置き換えるかという点です。 代替ツールを検討する前に、まず Chromatic から得ていた主な価値を整理しました。

Chromatic から得ていた価値 💎

Chromatic は単なる VRT ツールにとどまらず、フロントエンドの開発フローおよび品質保証に幅広く価値を提供しています。

特に以下の 3 つの価値が重要でした:

  1. リグレッションの検知

    • UI に意図しない変更が入っていないかを自動的に検知
    • 継続的な品質保証の基盤
  2. 開発体験の向上

    • PR の変更によって UI にどのような影響があるかを視覚的に確認
    • Story 単位での変更承認/拒否により、コンポーネントごとの細かなレビューが可能
  3. Storybook 共有によるコミュニケーション基盤

    • デザイナーやプロダクトマネージャーとのコミュニケーションツールとして機能
    • 再現が難しい条件の UI 状態も、Storybook でパラメータを固定して共有可能
    • コンポーネントの全バリエーションを一覧できるカタログとしての役割

これらの価値をできる限り維持しながら内製化を進める必要がありました。

Storybook のホスティングを代替する

「3. Storybook 共有によるコミュニケーション基盤」について、Storybook をホスティングできることについては、Storybook 自体は静的な配信に対応しています。

ですので、単に「ブランチごとにビルドをして AWS S3 等のホスティングが行えるサービスでホスティングする」仕組みだけ作れれば良いので、GitHub Actions で AWS S3 にアップロードするワークフローを組むことで対応できる見立てが立ちました。

VRT の実行およびレポート確認を代替する

Storycap + reg-suit

Storycapreg-suit の組み合わせは、オープンソースで VRT を実現する広く使われているオプションです。

VRT の実現には、大きく分けて

  1. スクリーンショットを撮影する部分
  2. UI の差分を検知する部分
  3. レポートを表示する部分

の要素が必要ですが、Storycap が 1 の撮影部分を、reg-suit が 2 と 3 の差分の検知とレポート部分をカバーします。

実際に既存の Storybook に組み込んでみて挙がった課題点とそれぞれの対応案は以下の通りです:

  1. ビューポートサイズ 📱: デフォルトでは正方形に近いサイズで、多くのページでは適切ではなかった

    • 対応: デフォルトのビューポート指定を追加(823 x 1,512)
  2. CSS アニメーション 🔄: ローディングアニメーションが diff になる問題

    • 対応: 提供される disableCssAnimation では固定できなかったので、isSnapshot モード時にスピナーのアニメーションを停止する Storybook のデコレータを追加することで対応
  3. Play Function ▶️: Chromatic では自動的に待機していた Play Function の完了を待たない問題

    • 対応: delay 指定または明示的に waitFor を使用

それぞれの課題も個別対応できることが分かり、十分実用に耐えそうだということで確認できました。

また、reg-suit によるレポートも視覚的にわかりやすく、差分の確認方法も複数用意されています。

Lost Pixel

Storybook ベースの VRT を実現する他のツールとして、Lost Pixel も検証しました。

Lost Pixel は reg-suit + Storycap 同様に Storybook のスクリーンショットを撮影し、変更を検知するためのツールです。Platform 版(SaaS)と OSS 版の 2 つの選択肢がありますが、OSS 版を検討しました。

Lost Pixel は前述の要素において 1 と 2 をサポートします。 差分はどうやって把握するのかというと、最新のスクリーンショットをコミットしておき、スクショを更新することで GitHub の PR の UI から確認する思想で作られています。

自分はあまり使ったことはなかったんですが、複数の差分表示方法を GitHub が対応していて変更内容自体はわかりやすく確認が可能でした。

実際に試用した結果、以下のような特徴がわかりました:

  • セットアップの容易さ : 設定が reg-suit 系に比べて「Easy」によっており、ほぼデフォルト設定だけで動作する
  • 安定性: Chromatic や reg-suit で個別・特殊対応が必要だったケースも、特に追加設定なく安定して動作していた

かなり Easy かつ安定した VRT が実現できていて感触はかなり良かったです。

一方、課題点 も見つかりました。

  • 実行速度が遅く、ローカルマシン(M2 Max 64GB Mac) でスクリーンショットのみで約 9 分
  • 並列化のオプションは提供されるが、sharding のオプションがなく大規模プロジェクトでの実行時間短縮が難しい
  • ほとんどカスタマイズは不要でしたが、Story 単位のオプション制御は弱くドキュメンテーションも限定的でカスタマイズはしづらい
  • レポート機能が提供されず、GitHub の diff に依存する必要がある

技術比較と選定 ⚖️

上記の検証結果をまとめると以下のようになります:

各ステップにおけるツール比較

スクリーンショットの capture

ツール 良い点 悪い点
Storycap 実行時間に難はあるが、並列化および sharding オプションが提供され、スケールに耐える Chromatic よりフレイキー気味で個別対応が必要になりがち。play function 非対応
Lost Pixel (OSS) 安定している 実行時間に難があるかつ sharding できないのでスケールに限界

リグレッション検知・レポート

ツール・サービス 差分チェックの体験
reg-suit レポート UI が提供され Chromatic に近く使いやすい体験。Story ごとの Accept/Deny/Comment ができない点は Chromatic に劣る
Lost Pixel (OSS) レポートは提供されず、ローカルまたは CI で新しいスクショをコミットし、GitHub の diff で確認する想定

事例はほとんど見かけませんでしたが

  • スクショ部分を Lost Pixel
  • リグレッション検知とレポート部分は reg-suit

のような構成も一応取ることができるので、併用する案も含めてそれぞれ選定を行い、reg-suit + Storycap の構造を取ることに決めました。

理由:

  • スクリーンショットの capture :
    • Lost Pixel も簡単かつ Flaky さが少なくて感触は良かったのですが、実行時間のスケーリングが厳しそうな点で選択できないと判断しました
    • 検証時点でも 1000 以上の Story が存在しており、今後も増えていくことを考えると sharding が不可能な点は致命的でした
  • リグレッション検知・レポート:
    • Chromatic に習熟している開発者の生産性を極力落とさずに移行してもらうためにもレポート画面がある点で reg-suit は魅力的だったため、採用しました
    • Lost Pixel の場合、ワークフローが煩雑になってしまう点もマイナスポイントでした

reg-suit + Storycap の構成では、Chromatic と比較すると開発者体験は若干劣るものの、以下の点で優位性がありました:

  1. コスト 💰: 大幅な削減が見込める
  2. カスタマイズ性 🛠️: ワークフローの各段階をカスタマイズ可能
  3. 実行環境の制御 🎮: 自社環境で実行するため、実行ノードのスペックやタイミングを制御可能

一方で、以下のトレードオフが存在します:

  1. 開発者体験の低下:

    • Story ごとの Accept/Deny/Comment ができない
    • 差分確認は GitHub のコメントを使ったやり取りになる
    • 特殊な Story に対するカスタム対応が必要になる場合がある
  2. 運用コスト :

    • 初期構築と継続的なメンテナンスが必要
    • GitHub Actions の実行時間と費用のバランス調整が必要

これらの比較を行い、コスト削減効果と許容できる開発者体験のバランスを考慮し、Storycap + reg-suitを採用することで決定しました。 やや開発体験の低下はあるものの、十分許容できるラインと判断しました。

まとめ 📝

Chromatic からの移行を検討する過程で、複数の VRT を提供する OSS とアプローチを検証しました。 その結果、コスト削減効果と開発者体験のバランスから、Storycap + reg-suit の組み合わせが最適であるという結論に至りました。

主な決め手となったポイントは以下の通りです:

  1. 大幅なコスト削減: 月額費用の大幅な削減が見込める
  2. 許容可能な開発者体験: 体験は Chromatic には若干劣るものの、主要な機能は維持できる
  3. 1-2 を満たしながら現実的な CI の実行時間を維持できる

今回は採用しませんでしたが、組織が小さいタイミングでの Chromatic はほぼ最低限のセットアップで高度な開発体験を提供してくれますし、Lost Pixel (OSS 版) も簡単さ・安定性で優位があり、重視するトレードオフによって良い選択肢だなと思いました。

次回予告

後編では、Storycap + reg-suit を使ったワークフローを実際に構築していく際の工夫した点や移行のプロセスについて紹介する予定です!

お楽しみに!