Jestのスナップショット機能を使ってみた
Jestとは
スナップショットテストとは
- スナップショット != スクリーンショット
- 画像の差分を取るのではない
- 出力されるHTMLの構造を比較する
Worcに導入してみた
Twitterクライアント、Windowsも対応しました〜https://t.co/HDikkJPm4P
— シベ (@shibe97) 2017年3月14日
(別件ですが、先日Windowsにも対応しました!)
Worcはかなり細かくコンポーネントを分けているので、試しやすかった。
完全に自分にとっての実験環境になりつつある・・・
対象のコンポーネント
とりあえず今回は、ツイート部分のテキストエリアコンポーネントを対象としてテストを行なった。
以下のようなコンポーネント。
1 import React from 'react'; 2 import styles from './textarea.css'; 3 4 export default ({ value = '', inputUpdate }) => ( 5 <textarea 6 className={styles.textarea} 7 placeholder="What's happening?" 8 value={value} 9 onChange={e => inputUpdate(e.target.value)} 10 /> 11 );
スナップショット機能の使い方
スナップショット機能を使うにはreact-test-renderer
というパッケージが必要。
$ npm i -D jest react-test-renderer
今回は対象のコンポーネントと同階層にテストファイルも置いた。
テストファイルの中身は以下のような感じ。
1 import React from 'react'; 2 import renderer from 'react-test-renderer'; 3 4 import Textarea from './Textarea'; 5 6 describe('components/atoms/textarea', () => { 7 it('renders correctly', () => { 8 const tree = renderer.create( 9 <Textarea value="test" inputUpdate={() => {}} /> 10 ).toJSON(); 11 expect(tree).toMatchSnapshot(); 12 }); 13 });
スナップショットが生成される場所
テストを実行すると、テストファイルが置いてある階層に__snapshots__
ディレクトリが生成される。
このディレクトリ内にスナップショットファイルが入る。
. ├── Textarea.js ├── Textarea.test.js ├── __snapshots__ │ └── Textarea.test.js.snap └── textarea.css
生成されたスナップショット
次のようなスナップショットファイルが生成される。
exports[`components/atoms/textarea renders correctly 1`] = ` <textarea className="textarea" onChange={[Function]} placeholder="What\'s happening?" value="test" /> `;
テスト時にこのファイルと常に比較され、差分があるとこける。
そのままでは修正するたびにこけてしまうし、意図的な変更をする場合でもテストがこけてしまう。
そこでスナップショットを更新するオプションが用意されている。
$ npm test -- -u
ちなみに--
はエスケープの役割だそう。
npm test
でjest
が呼ばれるようにpackage.json
のscripts
に設定してある。
試しに少し変更を入れてテストを走らせてみる
valueの部分にtestという文字列を付け加える。
1 import React from 'react'; 2 import styles from './textarea.css'; 3 4 export default ({ value = '', inputUpdate }) => ( 5 <textarea 6 className={styles.textarea} 7 placeholder="What's happening?" 8 value={`${value}test`} 9 onChange={e => inputUpdate(e.target.value)} 10 /> 11 );
この状態でテストを走らせると次のようになる。
差分がとても分かりやすく表示されている。
オプションを付けてスナップショットを更新するとエラーはなくなる。
Worcでの運用方法
とりあえず以下のようにしてみた。けどもっと良い運用方法あるはず。
皆どうしているんだろうか。
- 元々push時にCIで
npm test
を回していた - しかし、CI上で
npm test -- -u
してしまうとスナップショットテスト全て通過してしまうので意味がなくなってしまう - そこで、push直前に
npm test
して、うまくいった場合にCI上でnpm test -- -u
を行う - push直前の処理はGit hooksを利用
Git hooksとは
Gitコマンドにフックして何らかの処理を行わせる仕組み。
.git/hooks
以下のシェルファイルをいじると動く。
- pre-commit
- post-commit
- pre-push
- post-push
- pre-receive
- post-receive
- etc…
今回自分はpre-push
を利用。
.git
以下はGitHubで共有できないので、postinstall時などに書き換えるようなスクリプトを用意する必要がある
まとめ
スナップショットという単語に興味は持っていたけどずっと触れていなくて、ついに試すことができて良かった。 非常に簡単にテスト実行まで試すことができたので、誰でもさくっと導入できると思う。。
難しいと思うのは運用面で、複数個所がエラーで落ちた際に、本当は正解なのに前回のスナップショットを正としているためエラーとなってしまっているパターンが混ざっていると、その切り分けをしなくてはならないのが大変だと思った。
このあたりはよく考えれば良い解決方法がありそうなので、色々と試していきたい。