検索
ホームページウェブフロントエンドCSSチュートリアル反応統合テスト:カバレッジが増え、テストが少なくなります

反応統合テスト:カバレッジが増え、テストが少なくなります

Reactで構築されたようなインタラクティブなWebサイトの場合、統合テストは自然な選択です。エンドツーエンドテストの追加オーバーヘッドなしで、ユーザーがアプリケーションと対話する方法を検証します。

この記事では、単純なWebサイトから始まり、単体テストと統合テストを使用して動作を検証するエクササイズで説明し、統合テストがコード行の少ない価値をより大きく達成する方法を示します。この記事では、ReactとJavaScriptでのテストに精通していると想定しています。 JestおよびReact Testingライブラリに精通することは役立ちますが、必要ありません。

テストには3つのタイプがあります。

  • ユニットテストは、コードの一部を独立して検証します。彼らは簡単に書くことができますが、全体像を無視するかもしれません。
  • エンドツーエンドテスト(E2E)サイプレスやセレンなどの自動フレームワークを使用して、ユーザーなどのWebサイトと対話します。ページのロード、フォームの記入、ボタンのクリックなど。それらは通常、ゆっくりと書かれて実行されますが、実際のユーザーエクスペリエンスに非常に近いです。
  • 統合テストはその間のどこかにあります。アプリケーションの複数のユニットがどのように連携するかを確認しますが、E2Eテストよりも軽いです。たとえば、Jestには、統合テストを容易にするためのいくつかの組み込みユーティリティが付属しています。 Jestは、バックグラウンドでJSDOMを使用して、自動化よりもオーバーヘッドが少ない一般的なブラウザAPIをシミュレートし、その強力なモッキングツールは外部API呼び出しをシミュレートできます。

別の注意事項:Reactアプリケーションでは、単体テストと統合テストが同じ方法で記述され、ツールが使用されます

反応テストを開始します

ログインフォームを使用して、Simple Reactアプリケーション(GitHubで利用可能)を作成しました。私はそれをreqres.inに接続します。これは、フロントエンドプロジェクトのテストに使用することがわかった便利なAPIです。

正常にログインできます。

...またはAPIからのエラーメッセージが発生します。

コード構造は次のとおりです。

 <code>LoginModule/ ├── components/ │ ├── Login.js // 渲染LoginForm、错误消息和登录确认│ └── LoginForm.js // 渲染登录表单字段和按钮├── hooks/ │ └── useLogin.js // 连接到API 并管理状态└── index.js // 将所有内容整合在一起</code>

オプション1:ユニットテスト

私のようなテストを書くのが好きなら(ヘッドフォンを着て、Spotifyで素敵な音楽を演奏することもあれば、各ファイルの単位テストを書くことに抵抗できないかもしれません。

テスト愛好家でなくても、明確な戦略なしで「テストの良い仕事をしようとする」プロジェクトに取り組んでいる可能性があり、テスト方法は「すべてのファイルに独自のテストが必要だと思いますか?」

これは次のように見えます(明確にするためにテストファイル名にユニットを追加しました):

 <code>LoginModule/ ├── components/ │  ├── Login.js │  ├── Login.unit.test.js │  ├── LoginForm.js │  └── LoginForm.unit.test.js ├── hooks/ │  ├── useLogin.js │  └── useLogin.unit.test.js ├── index.js └── index.unit.test.js</code>

GitHubでエクササイズを完了してこれらすべてのユニットテストを追加し、テストを作成しました:カバレッジ:カバレッジレポートを生成するユニットスクリプト(JESTの組み込み機能)。 4つのユニットテストファイルを使用して、100%のカバレッジを達成できます。

通常、100%のカバレッジは圧倒的ですが、このような単純なコードベースでは可能です。

Onlogin Reactフック用に作成された単体テストの1つを掘り下げましょう。 Reactフックやテスト方法に慣れていない場合は、心配しないでください。

テスト( '成功したログインフロー'、async()=> {
 //成功したAPI応答Jestをシミュレートします
  .spyon(window、 'fetch')
  .MOCKRESOLVEDVALUE({json:()=>({token: '123'})});

 const {result、waitfornextupdate} = renderhook(()=> uselogin());

 act(()=> {
  result.current.Onsubmit({
   電子メール: '[電子メール保護]'、
   パスワード:「パスワード」、
  });
 });

 //ステータスを保留中に設定します
 expect(result.current.state).toequal({
  ステータス:「保留中」、
  ユーザー:null、
  エラー:null、
 });

 waitfornextupdate()を待ちます。

 //ステータスを解決に設定してメールアドレスを保存します
  ステータス:「解決済み」、
  ユーザー:{
   電子メール: '[電子メール保護]'、
  }、
  エラー:null、
 });
});

このテストは、React Hooks Testing Libraryがテストフックを簡単にするため)に書くのが興味深いですが、いくつかの問題があります。

まず、テスト検証内部状態は「保留中」から「解決」に変更されます。この実装の詳細はユーザーにさらされていないため、テストするのは良いことではないかもしれません。アプリケーションをリファクタリングする場合、ユーザーの観点から何も変わらなくても、このテストを更新する必要があります。

また、単体テストとして、これはその一部にすぎません。送信ボタンテキストを「読み込み」に変更するなど、ログインプロセスの他の機能を確認する場合は、別のテストファイルで実行する必要があります。

オプション2:統合テスト

このプロセスを検証するために、統合テストに代わるものを追加することを考えてみましょう。

 <code>LoginModule/ ├── components/ │  ├── Login.js │  └── LoginForm.js ├── hooks/ │  └── useLogin.js ├── index.js └── index.integration.test.js</code>

このテストとテスト:カバレッジ:統合スクリプトを実装して、カバレッジレポートを生成しました。ユニットテストと同様に、100%のカバレッジに達することができますが、今回はすべて1つのファイルにあり、コードの行が少なくなります。

成功したログインプロセスをカバーする統合テストは次のとおりです。

 test( '成功ログイン'、async()=> {
  冗談
    .spyon(window、 'fetch')
    .MOCKRESOLVEDVALUE({json:()=>({token: '123'})});

  与える(<loginmodule></loginmodule> );

  const emailfield = screen.getByrole( 'textbox'、{name: 'email'});
  const passwordfield = screen.getByLabelText( 'password');
  const button = screen.getByrole( 'Button');

  // fireevent.change(emailfield、{target:{value: '[email protected]'}});
  fireevent.change(passwordfield、{target:{value: 'password'}});
  fireevent.click(ボタン);

  // Load State expect(button).tobedisabled()を設定します。
  expect(button).tohaveTextContent( 'Loading ...');

  待機中(()=> {
    // form element expect(button).not.tobeinthedocument();
    expect(emailfield).not.tobeinthedocument();
    expect(passwordfield).not.tobeinthedocument();

    //成功テキストとメールアドレスconst loggedintext = screen.getByText( 'ログインas');
    expect(loggedintext).tobeinthedocument();
    const emailaddresstext = screen.getByText( '[電子メール保護]');
    expect(emailaddresstext).tobeinthedocument();
  });
});

このテストは、ユーザーの観点からログインプロセス全体を検証するため、フォーム、ロードステータス、および成功した確認メッセージを検証するため、私は本当に気に入っています。統合テストは、正確にはこのユースケースのために、Reactアプリケーションに最適です。ユーザーエクスペリエンスは私たちがテストしたいものであり、これにはほとんどの場合、一緒に動作するコードの複数の異なるスニペットが含まれます。

このテストは、予想される動作を機能させるコンポーネントまたはフックを理解していません。これは素晴らしいことです。ユーザーエクスペリエンスが同じままである限り、テストを破ることなく、これらの実装の詳細を書き換えてリファクタリングすることができます。

エラー処理のためにログインプロセスの初期状態やその他の統合テストを掘り下げることはありませんが、GitHubで表示することをお勧めします。

それで、単体テストに何が必要ですか?

ユニットテストと統合テストを検討するのではなく、一歩後退して、そもそもテストする必要があるものをどのように決定するかを考えてみましょう。 LoginModuleは、ユーザー(アプリケーションの他のファイル)に自信を持って使用できるようにしたいエンティティであるため、テストする必要があります。

一方、LoginModuleの実装の詳細だけであるため、Onloginフックをテストする必要はありません。ただし、要件が変更され、Onloginが他の場所に使用ケースがある場合は、独自の(ユニット)テストを追加して、その機能を再利用可能なユーティリティとして検証する必要があります。 (ファイルもログインモジュールに固有ではないため、ファイルを移動する必要があります。)

単体テストには、再利用可能なセレクター、フック、通常の機能を検証する必要性など、まだ多くのユースケースがあります。コードを開発するときは、後で統合テストにそのロジックを移動しても、単体テスト駆動型開発を使用することも役立つ場合があります。

さらに、ユニットテストは、複数の入力とユースケースの徹底的なテストの素晴らしい仕事をします。たとえば、私のフォームがさまざまなシナリオのインライン検証を表示する必要がある場合(たとえば、無効な電子メール、パスワードが欠けている、パスワードが短すぎる)、統合テストで代表的なケースをカバーし、単体テストで特定のケースを掘り下げます。

その他の利点

私たちがここにいるので、統合テストを明確で整然と保つのに役立ついくつかの構文のヒントについてお話したいと思います。

ブロックをクリアします

私たちのテストでは、荷重状態とログインモジュールの成功状態の間の遅延を考慮する必要があります。

 const button = screen.getByrole( 'Button');
fireevent.click(ボタン);

expect(button).not.tobeinthedocument(); //速すぎると、ボタンはまだそこにあります!

DOMテストライブラリのWaitfor Helper機能を使用してこれを行うことができます。

 const button = screen.getByrole( 'Button');
fireevent.click(ボタン);

待機中(()=> {
 expect(button).not.tobeinthedocument(); //ああ、それははるかに優れています});

しかし、他のプロジェクトをテストしたい場合はどうなりますか?これをどのように処理するかについてインターネット上には多くの良い例はありません。過去のプロジェクトでは、他のプロジェクトをWaitfor以外に置きました。

 //待機ボタンを待ってくださいwaitfor(()=> {
 expect(button).not.tobeinthedocument();
});

//次に、確認メッセージconst confirmentationtext = getByText( '[電子メール保護]');
expect(cusmentationtext).tobeinthedocument();

これは機能しますが、これらのステートメントの順序を簡単に切り替えることができても、ボタン状態を特別に見せるため、私はそれが好きではありません。

 //確認メッセージが待機するのを待ってくださいwaitfor(()=> {
 const cundimationText = getByText( '[電子メール保護]')としてログインします ');
 expect(cusmentationtext).tobeinthedocument();
});

// [ボタン] [ボタン).not.tobeinthedocument()をテストします。

同じアップデートに関連するすべてをWaitfor Callbackにグループ化する方がはるかに良いように思えます。

待機中(()=> {
 expect(button).not.tobeinthedocument();

 const cundimationText = screen.getByText( '[電子メール保護]')としてログインします ');
 expect(cusmentationtext).tobeinthedocument();
});

私はこのような単純な主張のためのこの手法が本当に好きですが、場合によってはテストを遅くすることができ、Waitforのすぐ外で発生する失敗を待っています。この例については、React Testing Libraryの共通エラーの「コールバックの1回の待機中の複数のアサーション」を参照してください。

いくつかのステップを含むテストの場合、複数の待機を連続して使用できます。

 const button = screen.getByrole( 'Button');
const emailfield = screen.getByrole( 'textbox'、{name: 'email'});

// fireevent.change(emailfield、{target:{value: '[email protected]'}})のフォームに記入します。

待機中(()=> {
 //ボタンが有効になっているかどうかを確認する(ボタン).not.tobedisabled();
  expect(button).tohavetextcontent( 'submit');
});

// fireevent.click(button);

待機中(()=> {
 //ボタンが存在しなくなったかどうかを確認します(ボタン).not.tobeinthedocument();
});

アイテムが1つだけ表示されるのを待っている場合は、代わりにFindByクエリを使用できます。バックグラウンドでWaitforを使用します。

インラインITコメント

別のテストベストプラクティスは、より少ない、より長いテストを書くことです。これにより、テストケースを重要なユーザープロセスと相関させることができ、予期しない動作を避けるためにテストを隔離し続けることができます。私はこのアプローチに同意しますが、コードを整理し、必要な動作を文書化することに課題をもたらす可能性があります。将来の開発者がテストに戻り、それが何をしているのか、なぜ失敗するのかを理解できるようにする必要があります。

たとえば、これらの期待の1つが失敗し始めたとします。

それ( '成功したログインフローを処理します'、async()=> {
 //明確にするためにテストの開始を非表示にします

  (ボタン).tobedisabled();
  expect(button).tohaveTextContent( 'Loading ...');


 待機中(()=> {
  expect(button).not.tobeinthedocument();
  expect(emailfield).not.tobeinthedocument();
  expect(passwordfield).not.tobeinthedocument();


  const cundimationText = screen.getByText( '[電子メール保護]')としてログインします ');
  expect(cusmentationtext).tobeinthedocument();
 });
});

このコンテンツを見る開発者は、テストされているものを簡単に判断できず、障害がバグ(コードを修正する必要があることを意味する)か、動作の変更(テストを修正する必要があることを意味します)であるかどうかを判断するのが難しい場合があります。

私のお気に入りのソリューションは、テストごとにあまり知られていないテスト構文を使用し、テストされている各重要な動作を説明するインラインスタイルのコメントを追加することです。

 test( '成功ログイン'、async()=> {
 //明確にするためにテストの開始を非表示にします

 //ロードステータスexpect(button).tobedisabled()を設定します。
  expect(button).tohaveTextContent( 'Loading ...');


 待機中(()=> {
  // form element expect(button).not.tobeinthedocument();
  expect(emailfield).not.tobeinthedocument();
  expect(passwordfield).not.tobeinthedocument();


  //成功テキストと電子メールアドレスconst confirmentationtext = screen.getByText( '[電子メール保護]');
  expect(cusmentationtext).tobeinthedocument();
 });
});

これらのコメントは魔法のようにJESTと統合されていないため、障害が発生した場合、テスト名の失敗はテストタグに渡されたパラメーター、この場合は「ログインの成功」に対応します。ただし、Jestのエラーメッセージには周囲のコードが含まれているため、これらのITコメントは依然として失敗した動作を識別するのに役立ちます。期待から削除しないと、次のエラーメッセージが表示されます。

より明示的なエラーを取得するために、各期待のエラーメッセージを定義できるJest-Expect-Messageというパッケージがあります。

想像(ボタン、 'ボタンはまだドキュメントにあります')。

一部の開発者はこのアプローチを好みますが、ほとんどの場合、私はそれが少しきめになりすぎていると思います。単一は通常、複数の期待を伴うためです。

チームの次のステップ

時々、私たちは人間のためにリナールールを作ることができたらいいのにと思います。もしそうなら、私たちはチームに優先統合テストルールを設定することができ、それは終わります。

しかし、残念ながら、以前に紹介したログインモジュールの例など、場合によっては開発者が統合テストを選択することを奨励するために、より類似したソリューションを見つける必要があります。ほとんどのことと同様に、それはあなたのテスト戦略について議論し、プロジェクトにとって何が理にかなっていることに同意し、そしてそれをADRで説明するチームに帰着します。

テスト計画を開発するときは、開発者が各ファイルのテストを作成するように強制する文化を避ける必要があります。開発者は、「アンダーテスト」を心配することなく、情報に基づいたテストの決定を自信を持って行うことができる必要があります。 Jestのカバレッジレポートは、テストが統合レベルでマージされたとしても、正気チェックを提供することにより、この問題を解決するのに役立ちます。

私はまだ自分自身を統合テストの専門家とは考えていませんが、この演習を行うと、統合テストがユニットテストよりも価値がある場合のユースケースを分解するのに役立ちました。これをチームと共有するか、コードベースで同様のエクササイズを行うことで、統合テストをワークフローに組み込むことができれば幸いです。

以上が反応統合テスト:カバレッジが増え、テストが少なくなりますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
スクリーンリーダーの分解:アクセス可能なフォームとベストプラクティススクリーンリーダーの分解:アクセス可能なフォームとベストプラクティスMar 08, 2025 am 09:45 AM

これは、フォームアクセシビリティについて行った小さなシリーズの3番目の投稿です。 2番目の投稿を逃した場合は、「ユーザーフォーカスの管理:Focus-Visible」をご覧ください。で

WordPressブロックと要素にボックスシャドウを追加しますWordPressブロックと要素にボックスシャドウを追加しますMar 09, 2025 pm 12:53 PM

CSS Box-Shadowおよびアウトラインプロパティは、WordPress 6.1でTheme.jsonサポートを獲得しました。実際のテーマでどのように機能するか、そしてこれらのスタイルをWordPressブロックと要素に適用するために必要なオプションのいくつかの例を見てみましょう。

GraphQLキャッシングの使用GraphQLキャッシングの使用Mar 19, 2025 am 09:36 AM

最近GraphQLの作業を開始した場合、またはその長所と短所をレビューした場合、「GraphQLがキャッシュをサポートしていない」または

最初のカスタムSvelteトランジションを作成します最初のカスタムSvelteトランジションを作成しますMar 15, 2025 am 11:08 AM

Svelte Transition APIは、コンポーネントがカスタムSVELTE遷移を含むドキュメントを入力または離れるときにアニメーション化する方法を提供します。

上品でクールなカスタムCSSスクロールバー:ショーケース上品でクールなカスタムCSSスクロールバー:ショーケースMar 10, 2025 am 11:37 AM

この記事では、Scrollbarsの世界に飛び込みます。私は知っています、それはあまりにも魅力的ではありませんが、私を信じてください、よく設計されたページは手をつないで行きます

ショー、Don&#039; t Tellショー、Don&#039; t TellMar 16, 2025 am 11:49 AM

あなたのウェブサイトのコンテンツプレゼンテーションの設計にどれくらいの時間に費やしますか?新しいブログ投稿を書いたり、新しいページを作成したりするとき、あなたは考えていますか

Redwood.jsと動物相を使用してイーサリアムアプリを構築しますRedwood.jsと動物相を使用してイーサリアムアプリを構築しますMar 28, 2025 am 09:18 AM

最近のビットコインの価格が20k $ $ USDを超えており、最近30Kを破ったので、イーサリアムを作成するために深く掘り下げる価値があると思いました

NPMコマンドは何ですか?NPMコマンドは何ですか?Mar 15, 2025 am 11:36 AM

NPMコマンドは、サーバーの開始やコンパイルコードなどの1回限りのプロセスまたは継続的に実行されるプロセスとして、さまざまなタスクを実行します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい