Jest を使ってスナップショットテストを行う
Jest は Facebook が中心になって開発している人気の JavaScript のテスティングフレームワークです。この記事では、 Jest の特徴的な機能であるスナップショットテストについて解説します。
スナップショットテストとは
システムの状態をある瞬間で切り取ったもの、あるいはバックアップのことをスナップショットと呼びますが、Jest におけるスナップショットの意味も同様です。
スナップショットテストでは、テストの対象になっている関数の出力をスナップショットとして保存し、コードの変更によってスナップショットに変更が生じているかどうかを検出(テスト)します。特に React などのフレームワークで UI を生成するコードに対するテストとしてスナップショットテストが行われていることが多いです。
スナップショットテストの何が嬉しいのか
UI を生成するためのコードは、複雑化しやすく、またユニットテストの対象となるロジックを抽出することが難しいものになりがちです。また、短いライフサイクルで UI の変更やリリースがあることを考えると、重厚なテストを実施しても開発のリソースの無駄遣いになってしまうことが懸念されます。
スナップショットテストを用いることで、最低限のリグレッションテスト、つまり、意図しない変更の発生を検出することができます。スナップショットテストは簡単に作成して実行することができるため、コストの面で優れています。
Jest で React コンポーネントのスナップショットを作成する
テスト環境のセットアップ
それでは実際にスナップショットテストを行ってみます。まずは React のスキャフォルディングツールの craeaste-react-app
を利用して React の開発環境を作成します。この環境には Jest もデフォルトでインストールされています。
スキャフォルディングが終わったら、React コンポーネントのスナップショットを作成するために必要なツールの react-test-renderer
をインストールします。
$ npx create-react-app sandbox-snapshot-testing $ npm install react-test-render --save-dev
この時点でnpm start
コマンドを使ってプロジェクトを実行し、正しく表示されることを確認しておきます。
$ npm start
テストコードの作成
テストコードを作成します。
src/App.test.js
import React from 'react' import App from './App' import renderer from 'react-test-renderer' it('matches to the snapshot', () => { const tree = renderer.create().toJSON() expect(tree).toMatchSnapshot() })
テストの実行
テストを実行します。
$ npm test
テストが成功しました。この時、__snapshots__
というディレクトリが作成され、コンポーネントのレンダリングの結果がスナップショットとして保存されています。
それではスナップショットテストをわざと失敗させてみます。 App.js
のコンポーネントのコードを変更し、UI を更新します。
some fix
という文字を追加して見た目を変更しています。この状態でテストを実行すると、
$ npm test
コンポーネントのレンダリングの結果がスナップショットとマッチせず、テストが意図通り失敗しました。
この UI の変更が意図したものであるときは、以下のコマンドでスナップショットを更新することができます。
$ npm test -- -u
スナップショットテストのワークフロー
__snapshots__
に作成されるスナップショットのデータのファイルは自動生成されたものです。自動生成ファイルを Git にコミットしないことは基本的な Git の約束事ではありますが、スナップショットのファイルは例外です。これらは Git にコミットして使います。 Git にスナップショットのデータがコミットされていることで、コミット毎にスナップショットテストの成功・失敗が保存されます。このことにより、 CI ツールなどとの連携が容易になります。