React×Storybook×JestでSnapshotテストを組む
前々から組んでみたかったのですが、今回仕事で組める機会に出会えたので重い腰を上げてやってみました。
間違っている内容も含んでいるかもですが、ご了承ください。
環境
- React(Next.js)
- CSS Modules
- TypeScript
- Jest
- Storybook
前提
『どうやって Snapshot テストって動かすの?』って思われている方は多いと思いますが、数日前の自分もそうでした。
ということで、Snapshot テストを組む前段階のフローを書いていこうと思います。
開発フロー
- React を用いてコンポーネントを作成する
簡単ですね。
Storybook を組む
- コンポーネント単位で Story ファイルを作成する。
これも簡単ですね、今回は 公式のドキュメント に沿って作成を行いました。
Storybook と Snapshot テストを組み合わせるメリット
テストの実行イメージとしては『テストランナー(今回は Jest)を使用し、Story ファイルからコンポーネントを render した結果を Snapshot として残す』というイメージです。
で、Story を組んでいる場合、Story 自体がそのままコンポーネントの render イメージとして使えるため、Snapshot 用に再度テストを書かなくて良いという大きなメリットが得られるわけですね。
裏を返せば Story ファイルを修正した場合、再度 Snapshot を撮る必要があるケースも出てくるってことですが、まぁ大したデメリットではないですね。
Snapshot テストの目的
自分はこれがずーっとわからなかったのですが、最近ようやく理解できました。
Snapshot テストを組むことによって得られる最大のメリットとは、コンポーネントの修正による影響範囲の把握が容易になること、これに尽きます。
Atomic Design を例にすると、Atoms や Molecules といった Presentational Components を修正した場合、上位のコンポーネントへの影響範囲は大きくなりがちです。
そういった場合、修正の際どのコンポーネントに影響があったのか、それを確実に把握することができるようになるのがとても大きいです。
仮に Snapshot テストを組んでいなければ、どのコンポーネントに影響があったかが、把握漏れが発生しやすくなってしまいます。
つまりプロジェクトの規模が大きくなればなるほど、Snapshot テストの恩恵は大きくなりますね。
Snapshot テストの実行
これも 1 つずつ順を追って説明をば。
Jest の環境作成
公式ドキュメント 通りでほぼ問題ないです。
ただしデフォルトでは TypeScript のサポートが入っていないので、あわせて導入 を行いましょう。
加えて Next.js の場合は babel.config.js に以下の設定もいるっぽいです。
module.exports = {
env: {
...
},
presets: [
...
"next/babel",
],
};
Snapshot テストの環境作成
公式ドキュメント にも記述があるのですが、アドオンのドキュメント と微妙に差異があってちょっとアレですが、どっちでも大丈夫です。
ドキュメントに沿ってアドオンの導入を行い、テストファイルを 1 つ切ってもらえれば完成です。
テストの実行
package.json あたりを以下のように書き換えます。
{
...,
"scripts": {
"build-storybook": "build-storybook",
"start:storybook": "npx serve storybook-static -p 8082",
"storybook": "start-storybook -p 6006",
"test": "jest",
"test:generate-output": "jest --json --outputFile=.jest-test-results.json"
},
}
あとは npm run test するなり npm run test:generate-output するなりわちゃわちゃしてもらえればと。
おそらくほとんどのケースでこのまま実行してもエラーを吐くと思います。
自分が引っかかったエラーとしては以下のとおりです。
- 絶対パスの対応
- Next.js への対応
- CSS および画像のモック対応
他にもちょこちょこありますが、調べたらすぐに引っかかるので本記事では省略します。