Storybook とスナップショットテストで API開発の完成を待たないフロント開発フロー

\*こちらは meguro.es の資料になります

---

# 自己紹介

株式会社オプト シニアエンジニア @sisisin（しめにゃん）

- [GitHub](https://github.com/sisisin)
- [Twitter](https://twitter.com/_sisisin)
- フロントエンドマン（最近は React+Redux）
- スクラムマスター・インフラ・サーバーサイドといろいろやります
- 今はテックリードとか社内アジャイル~~コーチ~~相談窓口っぽいことやってます

---

# 皆さん API とフロントの分業しますよね？

---

昨今は Swagger を使って API の interface を決めて、並列開発！
フロントも API も、interface を守って開発すればスムーズ！

---

# 並列に走っていたので、フロントが API より先に出来た！

---

# あれ？動作確認どうすれば・・・🤔

---

- ユニットテストで担保する？

- 実際のアプリ画面動くか試さなくて良い？

- UI の自動テストは大変だから API 側の完成を待つ？

---

### ユニットテストで担保する？

- DOM を find してマッチするテストを書く？
- でも UI ってすぐ変わるし・・・

---

# 😫

---

### 実際のアプリ画面動くか試さなくて良い？

- モックサーバー作って検証だ
- と思ったら API レスポンスに swagger で表現できない型がある・・・

---

# 😇

---

### UI の自動テストは大変だから API 側の完成を待つ？

- そしてエンバグ

---

# 😢

---

# そんな悩みをお抱えのあなた！

---

# Storybook+reg-suit でスナップショットテストの環境を用意すれば解決します、その問題！

---

# 前提

- React+Redux での話をします
- Angular+NgRx,Vue+Vuex などでも適用できる話ですが、読み替えは各自適宜お願いします
- Storybook を使ったスナップショットテストの担保する範囲と、それを活用するための story 設計の話をします
- Storybook などの導入方法の話は **しません**

---

# Storybook と reg-suit とは

## Storybook

React などの View ライブラリで作成したコンポーネントを単独で描画して、見た目をカタログちっくに見れる画面作成のためのライブラリ

## reg-suit

画像の diff を取って、差分があった場合に GitHub に通知することが出来る、ビジュアルリグレッションテストサービス

---

# Redux におけるユニットテストと Storybook による見た目のテストの担保する範囲について

いつもの図

<img width="1116" alt="flux.png" src="https://qiita-image-store.s3.amazonaws.com/0/54872/ad4747ef-f4a2-bf8a-a2a0-a6b7ff8bd32c.png">

---

## ユニットテスト

- `ActionCreator`,`Web API`,`Reducer`,`Store` `Store Queries` をカバー出来る

<img width="1116" alt="flux-ut.png" src="https://qiita-image-store.s3.amazonaws.com/0/54872/7dda745b-35bb-50f3-bcb0-1a72e50597fb.png">

---

## Storybook を使ったスナップショットテスト

- `Store`,`Store Queries`,`React Views`,`User Interactions` をカバー出来る
  - ＊`User Interactions`については、 Storybook のアドオンの`addon-actions`を利用した手動確認

<img width="1116" alt="flux-vt.png" src="https://qiita-image-store.s3.amazonaws.com/0/54872/f869b8a2-806a-0e8e-5b54-27edc6fa5225.png">

---

→API なしでも動作検証が全てカバーできる！

<img width="1116" alt="flux-sum.png" src="https://qiita-image-store.s3.amazonaws.com/0/54872/0aca279d-8d5d-809e-99f4-1f006d90da3d.png">

---

# Storybook+スナップショットテストを使った開発フロー

- `ActionCreator`,`Web API`,`Reducer`,`Store` `Store Queries` をテスト駆動で作る
  - `jest` などのテストランナーでローカル・CI ともに自動テスト
- `React View` を**Storybook 駆動**で作る
  - ローカルでは Storybook の画面を見ながら開発
  - `reg-suit`を使って CI で自動テスト

API が全く出来てなくてもフロントだけで開発が完結できる！！
CI での自動テストも完備！

---

# Store, Store Queries, React Views をカバーするための story 設計

大層なことを言いましたが、やることは以下の 2 点だけ

- テストのための story では Router で定義された各 RootComponent を描画する
- 描画する Component へ渡す props は `Store` （`redux state`）を元に、`Store Queries` （`mapStateToProps`）を使って生成

---

## ポイント

### テストのための story では Router で定義された各 RootComponent を描画する

- レイアウトまで含めたテストとしたいので
  - こうするとレスポンシブ対応などは恩恵を受けやすい
- 個々の Component についての story も必要に応じてやればよい
  - ただしその場合、Root を描画する story とは役割が異なるもの、という認識をチーム内で揃えておかないとカオスになりそう
  - 自動テストの文脈でいう「単体」なのか「結合」なのか、というノリで、Page テストと Component テスト、みたいなイメージ

---

## ポイント

### 描画する Component へ渡す props は `Store` （`redux state`）を元に、`Store Queries` （`mapStateToProps`）を使って生成

- Props べた書きで作ると追従がしんどいので、 基本的に`state`を元に作るようにする
  - 例えば同じ `string`型でも、`12%` が `12.00%`と表示されるように変わった場合などが辛い
  - こういうのを追従しないと、テストしてるものと実際に動いてるものが食い違うという状況になる

---

# 運用してみての感想

## 悩みどころ

- Component 内にある `redux container` Component をどう取り扱うか
  - initial state を storybook 環境だと固定値にしてしまう
  - storybook の中で Action を Dispatch して対処
- 見た目を色々調整するのに storybook 用の props 作る、などの対処が意外と頑張る必要がある
- つい Story 追加し忘れる
  - 新規画面はまだ良いが、修正系で直ったことを保証するようなケースの追加が漏れがち
  - 既に API があるものだと普通に画面見ながら開発しちゃうのでしょうがなさげ・・・

---

## 歯の食いしばりどころ

- CI での自動テストがランダムで落ちないように頑張る
  - アニメーション GIF とか
  - canvas が微妙に同じ結果にならない
  - スナップショットツールの挙動
- 仮に落ちるようになっちゃっても放置しない
  - 割れ窓になり、形骸化に繋がりうる
- サービス本体以外に、Storybook のビルドという依存が出来る問題
  - バージョンアップが辛い
  - ツールが噛み合わないときに辛い

---

# よかった点

- フロント先行で開発しても、API レスポンスの想定・ケース網羅周り以外でバグがあまり出なかった
  - 計測してないので体感
- CSS フレームワークのメジャーバージョンアップ、Component 周りのリファクタなどがやりたい放題
  - 最高！
- 自動テストでフロントの挙動がかなりカバーされているので、動作検証に割く時間を減らしても安心して開発できる
  - もうフロントはテストしにくいなんて言わせない
  - 最高！！

---

# おまけ

## 周辺ツール紹介

- [zisui](https://github.com/Quramy/zisui)
- [storybook-chrome-screenshot](https://github.com/tsuyoshiwada/storybook-chrome-screenshot)
  - Storybook の story を全部舐めて Screenshot を取ってくれるツール。これがないと始まらない
- [story2sketch](https://github.com/chrisvxd/story2sketch)
  - Storybook の Component を sketch に起こしてくれるツール。
    - 今回の話と直接関係ないが、デザイナーとの協業で便利
    - まだ使い込んでなくて上手く行ってないことも多いので、その辺知見たまったらまとめたい

---

# おわりに

というわけで Storybook とスナップショットテストを前提とした story 設計の話でした
最高なので是非使っていくべき

---

# Happy Hacking!