Jestを使用してReactアプリケーションをテストするための実用的なガイド

公開: 2022-03-10
簡単な要約↬適切に機能するアプリケーションを構築するには、適切なテストが必要です。 そうでなければ、アプリケーションが期待どおりに機能するかどうかを知ることは、当て推量と運の問題になります。 Jestは、Reactアプリケーションのテストに利用できる最高のツールの1つです。 この記事では、Reactコンポーネントとアプリケーションの堅実なテストを作成するために必要なすべてを学びます。

この記事では、Jestという名前のReactテストツールと、Reactコンポーネントをテストするために設計された人気のあるライブラリEnzymeを紹介します。 テストの実行、Reactコンポーネントのテスト、スナップショットテスト、モックなど、Jestのテスト手法を紹介します。 テストに不慣れで、どのように始めればよいか疑問に思っている場合は、テストの概要から始めるため、このチュートリアルが役立ちます。 これで、JestとEnzymeを使用してReactアプリケーションをテストできるようになります。 このチュートリアルに従うには、Reactに精通している必要があります。

テストの簡単な紹介

テストは、コードがどのように実行されるかを行ごとに確認することです。 アプリケーションの一連のテストには、アプリケーションが正常に実行され、エラーが発生していないかどうかを確認するためのさまざまなコードが含まれています。 コードを更新するときにも、テストは便利です。 コードの一部を更新した後、テストを実行して、更新によってアプリケーションの機能がすでに損なわれていないことを確認できます。

なぜテストするのですか?

なぜそれをする前に何かをするのかを理解するのは良いことです。 では、なぜテストするのか、そしてその目的は何ですか?

  1. テストの最初の目的は、リグレッションを防ぐことです。 リグレッションは、以前に修正されたバグの再現です。 特定のイベントが発生した後、機能が意図したとおりに機能しなくなります。
  2. テストにより、複雑なコンポーネントとモジュラーアプリケーションの機能が保証されます。
  3. ソフトウェアアプリケーションまたは製品の効果的なパフォーマンスを得るには、テストが必要です。

テストにより、アプリがより堅牢になり、エラーが発生しにくくなります。 これは、コードが目的どおりに機能し、アプリがユーザーの意図したとおりに機能することを確認する方法です。

ジャンプした後もっと! 以下を読み続けてください↓

テストの種類とその機能について見ていきましょう。

単体テスト

このタイプのテストでは、ソフトウェアの個々のユニットまたはコンポーネントがテストされます。 ユニットは、個々の関数、メソッド、プロシージャ、モジュール、またはオブジェクトである可能性があります。 単体テストは、ソフトウェアのコードの各ユニットが期待どおりに機能することを検証するために、コードのセクションを分離し、その正確性を検証します。

単体テストでは、個々の手順または機能が適切に動作していることを保証するためにテストされ、すべてのコンポーネントが個別にテストされます。 たとえば、関数をテストしたり、プログラム内のステートメントまたはループが正しく機能しているかどうかをテストすることは、単体テストの範囲に含まれます。

コンポーネントテスト

コンポーネントテストは、アプリケーションの個々の部分の機能を検証します。 テストは、他のコンポーネントから分離して各コンポーネントで実行されます。 通常、Reactアプリケーションは複数のコンポーネントで構成されているため、コンポーネントテストではこれらのコンポーネントを個別にテストします。

たとえば、多くのコンポーネントを含むさまざまなWebページがあるWebサイトについて考えてみます。 すべてのコンポーネントには、独自のサブコンポーネントがあります。 他のコンポーネントとの統合を考慮せずに各モジュールをテストすることを、コンポーネントテストと呼びます。

Reactでこのようにテストするには、より高度なツールが必要です。 そのため、Jestと、場合によってはEnzymeなどのより高度なツールが必要になります。これについては後で簡単に説明します。

スナップショットテスト

スナップショットテストでは、Webアプリケーションのユーザーインターフェイス(UI)が予期せず変更されていないことを確認します。 ある時点でのコンポーネントのコードをキャプチャするため、ある状態のコンポーネントを、他の可能な状態と比較できます。

スナップショットテストについては、後のセクションで学習します。

テストの長所と短所

テストは素晴らしく、実行する必要がありますが、長所と短所があります。

利点

  1. 予期しないリグレッションを防ぎます。
  2. これにより、開発者は過去を心配することなく、現在のタスクに集中できます。
  3. これにより、複雑すぎて構築できないアプリケーションのモジュラー構築が可能になります。
  4. 手動検証の必要性を減らします。

短所

  1. より多くのコードを記述し、デバッグと保守を行う必要があります。
  2. 重大ではないテストの失敗により、継続的インテグレーションの観点からアプリが拒否される可能性があります。

ジェスト入門

Jestは、シンプルさに焦点を当てた楽しいJavaScriptテストフレームワークです。 npmまたはYarnでインストールできます。 Jestは、テストランナーと呼ばれる幅広いカテゴリのユーティリティに適合します。 Reactアプリケーションには最適ですが、Reactアプリケーション以外でも有効に機能します。

Enzymeは、Reactアプリケーションをテストするために使用されるライブラリです。 コンポーネントをテストするように設計されており、UIが正しく機能しているかどうかを確認するアクションをシミュレートするアサーションを作成できます。

JestとEnzymeは互いに補完し合うので、この記事では両方を使用します。

Jestでテストを実行するプロセス

このセクションでは、Jestをインストールしてテストを作成します。 Reactを初めて使用する場合は、Create React Appを使用することをお勧めします。これは、すぐに使用でき、Jestに付属しているためです。

 npm init react-app my-app

Enzyme ****とenzyme-adapter-react-16react-test-rendererとともにインストールする必要があります(この数は、使用しているReactのバージョンに基づいている必要があります)。

 npm install --save-dev enzyme enzyme-adapter-react-16 react-test-renderer

JestとEnzymeの両方を使用してプロジェクトを作成したので、プロジェクトのsrcフォルダーにsetupTest.jsファイルを作成する必要があります。 ファイルは次のようになります。

 import { configure } from "enzyme"; import Adapter from "enzyme-adapter-react-16"; configure({ adapter: new Adapter() });

これにより、酵素がインポートされ、テストを実行するようにアダプターがセットアップされます。

続行する前に、いくつかの基本を学びましょう。 この記事ではいくつかの重要なことがよく使われているので、それらを理解する必要があります。

  • itまたはtestこのメソッドに関数を渡すと、テストランナーはその関数をテストのブロックとして実行します。
  • describeこのオプションのメソッドは、任意の数のメソッドまたはtestステートメントをグループ化するためのitです。
  • expectこれは、テストに合格する必要がある条件です。 受信したパラメータをマッチャーと比較します。 また、さまざまなことを検証できる多数のマッチャーにアクセスできます。 詳細については、ドキュメントをご覧ください。
  • mountこのメソッドは、テストを実行している親コンポーネントの子コンポーネントを含む完全なDOMをレンダリングします。
  • shallowこれは、テストしている個々のコンポーネントのみをレンダリングします。 子コンポーネントはレンダリングされません。 これにより、コンポーネントを個別にテストできます。

テストファイルの作成

Jestは、テストファイルとは何かをどのようにして知るのでしょうか。 最初のルールは、 __test__という名前のディレクトリで見つかったファイルはすべてテストと見なされるというものです。 これらのフォルダーの1つにJavaScriptファイルを置くと、Jestは、Jestを呼び出すときに、良くも悪くも、それを実行しようとします。 2番目のルールは、Jestがサフィックス.spec.jsまたは.test.jsを持つすべてのファイルを認識することです。 リポジトリ全体のすべてのフォルダとすべてのファイルの名前を検索します。

このチュートリアル用に作成されたReactミニアプリケーションの最初のテストを作成しましょう。 GitHubでクローンを作成できます。 npm installを実行してすべてのパッケージをインストールしてから、 npm startを開始します。 詳細については、 README.mdファイルを確認してください。

App.test.jsを開いて、最初のテストを作成しましょう。 まず、アプリコンポーネントが正しくレンダリングされるかどうか、および出力を指定したかどうかを確認します。

 it("renders without crashing", () => { shallow(<App />); }); it("renders Account header", () => { const wrapper = shallow(<App />); const welcome = <h1>Display Active Users Account Details</h1>; expect(wrapper.contains(welcome)).toEqual(true); });

上記のテストでは、 shallow最初のテストで、アプリコンポーネントがクラッシュせずに正しくレンダリングされるかどうかを確認します。 shallow方法では、子コンポーネントなしで単一のコンポーネントのみがレンダリングされることに注意してください。

2番目のテストでは、アプリコンポーネントで「アクティブユーザーアカウントの表示」のh1タグ出力を、 toEqualのJestマッチャーで指定したかどうかを確認します。

次に、テストを実行します。

 npm run test /* OR */ npm test

端末の出力は次のようになります。

 PASS src/App.test.js √ renders without crashing (34ms) √ renders Account header (13ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 11.239s, estimated 16s Ran all test suites related to changed files. Watch Usage: Press w to show more.

ご覧のとおり、テストに合格しました。 これは、 App.test.jsという名前のテストスイートが1つあり、Jestの実行時に2つのテストが成功したことを示しています。 スナップショットテストについては後で説明します。また、失敗したテストの例も表示されます。

テストをスキップまたは分離する

テストをスキップまたは分離することは、Jestが実行されるときに、特定のマークされたテストが実行されないことを意味します。

 it.skip("renders without crashing", () => { shallow(<App />); }); it("renders Account header", () => { const wrapper = shallow(<App />); const header = <h1>Display Active Users Account Details</h1>; expect(wrapper.contains(header)).toEqual(true); });

skipメソッドを使用してテストを分離したため、最初のテストはスキップされます。 そのため、Jestの実行時にテストが実行されたり、テストが変更されたりすることはありません。 2番目のものだけが実行されます。 it.only()を使用することもできます。

テストファイルに変更を加えてから、手動でnpm test再度実行する必要があるのは少しイライラします。 Jestには、ファイルの変更を監視し、それに応じてテストを実行する監視モードと呼ばれる優れた機能があります。 Jestを監視モードで実行するには、 npm test -- --watchまたはjest --watch --watchを実行できます。 また、このチュートリアルの残りの部分では、ターミナルウィンドウでJestを実行したままにしておくことをお勧めします。

モッキング機能

モックは、実際の内部動作がない、オブジェクトまたはモジュールの説得力のある複製です。 ほんの少しの機能があるかもしれませんが、本物と比較すると、それはモックです。 Jestによって自動的に作成することも、手動で作成することもできます。

なぜ私たちはあざける必要がありますか? モッキングにより、依存関係の数、つまり、テストの実行時にロードおよび解析する必要のある関連ファイルの数が減少します。 したがって、多くのモックを使用すると、テストの実行が速くなります。

モック関数は、出力をテストするだけでなく、他のコードによって直接呼び出される関数の動作をスパイできるため、「スパイ」とも呼ばれます。

関数をモックする方法は2つあります。テストコードで使用するモック関数を作成する方法と、モジュールの依存関係をオーバーライドする手動モックを作成する方法です。

手動モック****は、モックデータで機能をスタブ化するために使用されます。 たとえば、Webサイトやデータベースなどのリモートリソースにアクセスする代わりに、偽のデータを使用できるようにする手動のモックを作成したい場合があります。

次のセクションでは、モック関数を使用します。

Reactコンポーネントのテスト

このセクションでは、Reactコンポーネントのテスト方法を理解するためにこれまでに得たすべての知識を組み合わせます。 テストでは、コンポーネントの出力が予期せず他のものに変更されていないことを確認します。 正しい方法でコンポーネントを構築することは、テストを成功させるための最も効果的な方法です。

私たちができることの1つは、コンポーネントの小道具をテストすることです。具体的には、あるコンポーネントの小道具が別のコンポーネントに渡されているかどうかをテストします。 JestとEnzymeAPIを使用すると、モック関数を作成して、コンポーネント間で小道具が渡されているかどうかをシミュレートできます。

ユーザーアカウントの小道具をメインのAppコンポーネントからAccountコンポーネントに渡す必要があります。 ユーザーのアクティブなアカウントを表示するには、 Accountにユーザーアカウントの詳細を提供する必要があります。 ここでモックが役立ち、偽のデータを使用してコンポーネントをテストできます。

userの小道具のモックを作成しましょう。

 const user = { name: "Adeneye David", email: "[email protected]", username: "Dave", };

テストファイルに手動のモック関数を作成し、コンポーネントにラップしました。 ユーザーの大規模なデータベースをテストしているとしましょう。 テストファイルからデータベースに直接アクセスすることはお勧めできません。 代わりに、偽のデータを使用してコンポーネントをテストできるようにするモック関数を作成します。

 describe(" ", () => { it("accepts user account props", () => { const wrapper = mount(<Account user={user} />); expect(wrapper.props().user).toEqual(user); }); it("contains users account email", () => { const wrapper = mount(<Account user={user} />); const value = wrapper.find("p").text(); expect(value).toEqual("[email protected]"); }); }); describe(" ", () => { it("accepts user account props", () => { const wrapper = mount(<Account user={user} />); expect(wrapper.props().user).toEqual(user); }); it("contains users account email", () => { const wrapper = mount(<Account user={user} />); const value = wrapper.find("p").text(); expect(value).toEqual("[email protected]"); }); });

上記の2つのテストがあり、テスト対象のコンポーネントを取得するdescribeレイヤーを使用します。 テストに合格すると予想される小道具と値を指定することで、先に進むことができます。

最初のテストでは、マウントされたコンポーネントに渡した小道具が、上記で作成した模擬小道具と等しいかどうかを確認します。

2番目のテストでは、ユーザーの小道具をマウントされたAccountコンポーネントに渡します。 次に、 Accountコンポーネントにあるものに対応する<p>要素が見つかるかどうかを確認します。 テストスイートを実行すると、テストが正常に実行されていることがわかります。

コンポーネントの状態をテストすることもできます。 エラーメッセージの状態がnullに等しいかどうかを確認しましょう。

 it("renders correctly with no error message", () => { const wrapper = mount( ); expect(wrapper.state("error")).toEqual(null); }); it("renders correctly with no error message", () => { const wrapper = mount( ); expect(wrapper.state("error")).toEqual(null); });

このテストでは、 toEqual()マッチャーを使用して、コンポーネントエラーの状態がnullに等しいかどうかを確認します。 アプリにエラーメッセージがある場合、実行時にテストは失敗します。

次のセクションでは、別の驚くべき手法であるスナップショットテストを使用してReactコンポーネントをテストする方法について説明します。

スナップショットテスト

スナップショットテストは、テストと一緒に保存された参照スナップショットファイルと比較するために、ある時点でコンポーネントのコードをキャプチャします。 これは、アプリのUIの変更を追跡するために使用されます。

スナップショットの実際のコード表現はJSONファイルであり、このJSONには、スナップショットが作成されたときにコンポーネントがどのように見えたかの記録が含まれています。 テスト中、JestはこのJSONファイルの内容をテスト中のコンポーネントの出力と比較します。 それらが一致する場合、テストは合格です。 そうでない場合、テストは失敗します。

EnzymeラッパーをJestスナップショットテストと互換性のある形式に変換するには、 enzyme-to-jsonをインストールする必要があります。

 npm install --save-dev enzyme-to-json

スナップショットテストを作成しましょう。 初めて実行すると、そのコンポーネントのコードのスナップショットが作成され、 srcディレクトリの新しい__snapshots__フォルダーに保存されます。

 it("renders correctly", () => { const tree = shallow(<App />); expect(toJson(tree)).toMatchSnapshot(); });

上記のテストが正常に実行されると、現在のUIコンポーネントが既存のUIコンポーネントと比較されます。

それでは、テストを実行してみましょう。

 npm run test

テストスイートが実行されると、新しいスナップショットが生成され、 __snapshots__フォルダーに保存されます。 その後テストを実行すると、Jestはコンポーネントがスナップショットと一致するかどうかを確認します。

前のセクションで説明したように、Enzymeパッケージのshallowメソッドは、単一のコンポーネントのみをレンダリングするために使用されます。 子コンポーネントはレンダリングされません。 むしろ、コードを分離し、デバッグ時に優れた情報を取得するための優れた方法を提供します。 mountという名前の別のメソッドを使用して、テストを実行している親コンポーネントの子コンポーネントを含む完全なDOMをレンダリングします。

スナップショットを更新することもできます。テストを失敗させるために、コンポーネントにいくつかの変更を加えましょう。これは、コンポーネントがスナップショットファイルにあるものに対応しなくなったために発生します。 これを行うには、コンポーネントの<h3>タグを<h3> Loading...</h3>から<h3>Fetching Users...</h3>に変更しましょう。 テストが実行されると、これがターミナルで取得されます。

 FAIL src/App.test.js (30.696s) × renders correctly (44ms) ● renders correctly expect(received).toMatchSnapshot() Snapshot name: `renders correctly 1 - Snapshot + Received FAIL src/App.test.js (30.696s) × renders correctly (44ms) ● renders correctly expect(received).toMatchSnapshot() Snapshot name: `renders correctly 1 - Snapshot + Received

アクティブユーザーアカウントの詳細を表示する

-読み込み中... +ユーザーの取得...

7 | it( "正しくレンダリング"、() => { 8 | constラッパー= shallow( ); > 9 | expect(toJson(wrapper))。toMatchSnapshot(); | ^ 10 | }); 11 | 12 | / * it( "クラッシュせずにレンダリング"、()=> { オブジェクトで。 (src / App.test.js:9:27) › 1つのスナップショットが失敗しました。 スナップショットの概要 › 1つのテストスイートから1つのスナップショットが失敗しました。 コードの変更を確認するか、 `u`を押して更新します。 テストスイート:1つ失敗、合計1つ テスト:1回失敗、合計1回 スナップショット:1つ失敗、合計1つ 時間:92.274秒 変更されたファイルに関連するすべてのテストスイートを実行しました。 使用法を見る:wを押して詳細を表示します。

テストに合格したい場合は、テストを以前の状態に変更するか、スナップショットファイルを更新します。 コマンドラインで、Jestはスナップショットを更新する方法についての指示を提供します。 まず、コマンドラインでwを押して詳細を表示し、次にuを押してスナップショットを更新します。

 › Press u to update failing snapshots.

uを押してスナップショットを更新すると、テストに合格します。

結論

このチュートリアルを楽しんでいただけたでしょうか。 Enzymeテストライブラリを使用して、いくつかのJestテスト手法を学びました。 また、テストの実行、Reactコンポーネントのテスト、モック、スナップショットテストのプロセスについても紹介しました。 ご不明な点がございましたら、下のコメント欄にご記入ください。すべての質問にお答えし、問題を解決させていただきます。

リソースと参考資料

  • ジェストのドキュメント
  • 酵素のドキュメント
  • 「Reactコンポーネントをテストする方法:完全ガイド」、Mohammad Iqbal、freeCodeCamp
  • 「JestとEnzymeを使用したReactのテスト」、Dominic Fraser、CodeClan