TokyoFacebookTwitterHatenaPocket「生まれ変わったFacebook製テストフレームワーク「Jest」とは何か?」に続き、テストフレームワーク「Jest」を使ったReactコンポーネントのテスト方法について解説します。スナップショットを使ったテスト方法は必読です。Reactコンポーネントをテストする注目すべきは、デフォルトではReactコンポーネントにあまりたくさんテストを記述しすぎない方が良いことです。ビジネスロジックなどのかなり徹底的にテストしたいものは、前述のステート関数のテストのようにコンポーネントから引き出して独立した関数に置くべきです。言っても、Reactのインタラクションをテストするときには便利です(たとえばユーザーがボタンをクリックしたときに特定の関数が正しい引数で呼び出されるか確認するなど)。Reactコンポーネントが正しいデータをレンダリングしているかテストすることから始め、そのあとテストのインタラクションを調べます。その次に、Reactコンポーネントの出力をテストする、はるかに便利なJestの機能スナップショットへ進みます。Reactコンポーネントが正しいデータをレンダリングしているかテストするには、Reactをテストする関数を提供するライブラリーreact-addons-test-utilsを使います。Airbnbによって書かれた、Reactコンポーネントのテストをとても簡単にするラッパーライブラリーEnzymeもインストールします。このAPIをテスト全体で使用します。Enzymeはすばらしいライブラリーで、ReactチームがReactコンポーネントをテストする方法として勧めています。enzymeTodoコンポーネントがパラグラフ内のtodoのテキストをレンダリングするかテストします。__tests__/todo.test.jsを作成し、コンポーネントをインポートします。{});また、Enzymeからもmountをインポートします。mount関数はコンポーネントのレンダリングに使用され、出力の検査やアサーションの作成ができます。Nodeでテストを実行しながらDOMを必要とするテストを書くこともできます。これはJestがDOMをNodeに実装するライブラリーjsdomを構成しているからです。テストのたびにブラウザーを立ち上げることなくDOMベースのテストを書けるのはすばらしいことです。Todoの作成にはmountを使用できます。/>);そして、Todoのテキストを含むパラグラフを見つけるためにwrapper.findを呼び出してCSSセレクターに渡します。このAPIのデザインは、jQueryを思い出させるかもしれません。これは、一致する要素を見つけるためにレンダリングされた出力を検索する、非常に直感的なAPIです。Milk内のテキストをアサートします。Milk');テスト全体は次のようになります。Milk」が画面に配置されるのを確認するために作業が多く労力がたくさんかかると思うかもしれません。確かにそのとおりです。次のセクションでは、これをもっと簡単にする機能を持つJestのスナップショットの使い方を取り上げます。関数が特定の引数で呼び出されていることをアサートするために、Jestのスパイ機能をどう使うか説明します。Todoコンポーネントには、ユーザーがボタンをクリックするかインタラクションを実行するときに呼び出すプロパティとして、2つの関数が与えられています。そのため、今回はこのスパイ機能が便利です。本テストでは、todoがクリックされたとき、コンポーネントが与えられているdoneChangeプロパティを呼び出すことをアサートします。{});呼び出しを追跡できる関数と、同時に呼び出される引数を置きたいとします。ユーザーがtodoをクリックするとdoneChange関数と正しい引数が呼び出されていることを確認します。ありがたいことにJestにはスパイが備わっています。スパイの実装については気にしなくても構いません。いつどのように呼び出されるかは気をつけてください。関数をスパイしていると考えてください。作成には次のようにjest.fn()を呼び出します。jest.fn();これは、スパイでできており正しく呼び出されているか確認できる機能を提供しています。それでは、正しいプロパティでTodoをレンダリングします。/>);次に、前述のテストと同じように、もう一度パラグラフを探します。'toggle-todo');それから、clickを引数として渡すユーザーイベントをシミュレーションするためにsimulateを呼び出します。p.simulate('click');あとはスパイ関数が正しく呼び出されていることをアサートするだけです。今回の場合はtodoのIDである1とともに呼び出されることを期待しています。これをアサートするためexpect(doneChange).toBeCalledWith(1)を使用します。それでテストは完了です。expect(doneChange).toBeCalledWith(1);});スナップショットを使用した優れたコンポーネントテストReactコンポーネントのテスト、特に(テキストレンダリングなどの)ありふれた機能の作業が多いと感じる可能性があることは、先に記しました。Jestでは、Reactコンポーネントで大量のアサーションをするのではなくスナップショットテストを実行します。これはインタラクションには不便ですが(その場合は上のようなテストをお勧めしますが)、コンポーネントの出力が正しいかテストするときには、とても簡単です。スナップショットテストを実行するとき、JestはReactコンポーネントをテスト下でレンダリングし、結果をJSONファイルに保存します。テスト実行のたびに、JestはReactコンポーネントがスナップショットと同じ出力をレンダリングをしているか確認します。コンポーネントの動作を変更すると、Jestが次のどちらかを知らせます。変更は意図的なものなので、Jestにスナップショットを更新この方法でのテストは以下のような意味になります。Reactコンポーネントが思いどおりに動作しているか確認するためにたくさんのアサーションを書く必要はないJestが感知するので、コンポーネントの動作が誤って変更されてしまうことはないまた、すべてのコンポーネントのスナップショットを作成する必要はなく、作成しないことを強く勧めます。動作確認する必要がある機能とコンポーネントのみを選択してください。すべてのコンポーネントのスナップショットを取ると、テストの速度が遅くなるだけで不便です。Reactは徹底的してテストされたフレームワークなので、期待どおりに動作すると確信を持って構いません。コードではなくフレームワークをテストする羽目にならないよう確かめてください。スナップショットのテストを開始するには、もう1つNodeパッケージが必要です。react-test-rendererは、Reactコンポーネントを受け取って純粋なJavaScriptオブジェクトとしてレンダリングできるパッケージです。これはファイルに保存されることを意味し、Jestがスナップショットを追跡し続けるために使用するものです。react-test-rendererでは、スナップショットを使用するために最初のTodoコンポーネントを書き直します。clickedテストもコメントアウトしてください。はじめにreact-test-rendererをインポートし、mountのインポートを削除します。両方を同時に使うことはできません。どちらか1つのみ使用します。テストをコメントアウトしたのは、これが理由です。'react-test-renderer';今度はレンダリングのためにインポートしたレンダラーを使い、スナップショットに適合していることをアサートします。});});最初の実行で、Jestはこのコンポーネントにはスナップショットが存在しないことを認識し、作成します。__tests__/snapshots/todo.test.js.snapを調べます。</a></div>`;Jestが出力を保存し、今後またこのテストを実行するときに出力が同じかどうか確認します。これを実証するために、todoのテキストをレンダリングするパラグラフを削除することでコンポーネントを壊してみます。以下の行をTodoコンポーネントから削除します。}</p>Jestは次のように反応します。(internal/process/next_tick.js:103:7)Jestはスナップショットが新しいコンポーネントと適合しないことに気がつくと、出力して知らせます。この変更が正しいと思われる場合は、Jestを-uフラグで実行してスナップショットを更新します。今回の場合は変更を取り消すことで問題がなくなりました。次に、インタラクションのテストにスナップショットのテストを使用する方法について取り上げます。テストごとに複数のスナップショットを持てるので、インタラクションが期待どおりかどうか出力をテストできます。それらはステートをコントロールせず、与えられたコールバックプロパティを呼び出すので、TodoコンポーネントのインタラクションをJestのスナップショットでテストすることはできません。todo.test.jsに残しています。これは、スナップショットのテストを異なるファイルに分離するのに便利だと分かりました。react-test-rendererとreact-addons-test-utilsの間のコンフリクトを受け取らないことを意味しています。記事に書いたコードはすべてGitHubにあるので、ローカルで実行してみてください。最後にFacebookがJestをリリースしたのはずいぶん前のことですが、ここ最近急激に取り上げられ開発が進んでいます。JavaScript開発者にどんどん好まれるようになり、改善されています。これまでフレームワークとはまったく異なるので、以前Jestを試したときは好みでなかった場合でも、ぜひもう一度試してみてください。高速で、再実行のスペックがすばらしく、エラーメッセージが的確で、さらにはスナップショットの機能が最高です。Franklinによるものです。SitePointのゲスト投稿では、JavaScriptコミュニティの著名な執筆者や講演者の魅力的なコンテンツの提供を目指しています。Pojerが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。Franklinロンドンで働くJavaScriptとRubyの開発者です。ツール作成、ES2015、ReactJSに重点的に取り組んでいます。