スナップショットテストとは?
スナップショットテストは、ある出力の「既知の正しい」バージョンを記録し、以降の実行が異なるものを生成した場合にテストを失敗させます。
スナップショットテストは、手書きのアサーションを自動的なベースラインと引き換えにします。最初の実行では、出力 - レンダリングされたコンポーネント、シリアライズされたオブジェクト、API レスポンス - を、保存されるスナップショットに取り込みます。以降の実行はそれと比較し、あらゆる差分をフラグします。これにより、詳細なアサートを書かなくても意図しない変更に気づけます。
仕組み
最初の実行で、テストフレームワークは出力をリポジトリにコミットされるスナップショットファイルに保存します。以降の実行では出力を再生成し、保存済みのスナップショットと差分比較します。一致すれば合格、不一致なら失敗して差分を表示し、変更を承認するか却下するかを求めます。
得意な場面
- レンダリングされた UI コンポーネントの意図しない変更を捉える。
- 大きなシリアライズ構造を低コストで固定する。
- 出力量の多いテストの定型コードを削減する。
- 偶発的なフォーマットや構造のずれを浮かび上がらせる。
うまくいかない場面
スナップショットは、大きすぎたり、不透明だったり、反射的に更新されたりすると負債になり得ます。差分を読まずに「すべてのスナップショットを更新」を実行する開発者は、セーフティネットを単なる形式的な承認印に変えてしまいます。スナップショットは小さく保ち、それらへのあらゆる変更を本物のコードと同じようにレビューしましょう。
簡単な例
コンポーネントのスナップショットテストは、コンポーネントをレンダリングして保存済みのベースラインと比較し、マークアップが変わった場合に失敗します。
test("renders button", () => {
const tree = render(<Button label="Save" />);
expect(tree).toMatchSnapshot();
});CI におけるスナップショットテスト
CI では、スナップショットは読み取り専用です。pipeline は不一致で失敗すべきであり、ベースラインを密かに書き換えてはいけません。ほとんどのフレームワークは、スナップショットの書き込みをブロックする ci フラグをサポートしています。これらのテストを高速な runner で実行すれば、大きなスナップショットの集合でも比較を低コストに保てます。
重要なポイント
- スナップショットテストは、新しい出力を保存されたベースラインと差分比較します。
- UI や構造の意図しない変更を捉えるのに非常に優れています。
- CI では、スナップショットは読み取り専用にし、更新は慎重にレビューする必要があります。