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 サイトの他の関連記事を参照してください。

独自のコードをリファクタリングするのはどのように見えますか?ジョン・レアは、彼が書いた古いCSSアニメーションを選び、それを最適化するという思考プロセスを歩きます。

cssanimationsArenotintinlentyhardbutrepracticeanderstanding ofcsspropertiesandtimingfunctions.1)

@keyframesispopularduetoitsversitility andpowerincreatingsmoothcssanimations.keytricksinclude:1)defingsmoothtransitionsbetweenstates、2)AnimatingMultipleProperiessimally、3)3)bendorprefixesforbrows -compativity、4)組み合わせwithjavasfo

csScounterSareSareusedTomageautomaticinginginwebdesigns.1)それらは、コンテンツ、リスト、および積極的なものを使用することができます

特にモバイルデバイスでは、スクロールシャドウを使用することは、Chrisが以前にカバーした微妙なUXです。 Geoffは、アニメーションタイムラインプロパティを使用する新しいアプローチをカバーしました。これがさらに別の方法です。

簡単に復習してみましょう。画像マップはHTML 3.2に戻ります。ここで、最初にサーバー側マップを使用してから、マップとエリア要素を使用して画像上でクリック可能な領域を定義したクライアント側マップをマップしました。

State of Devsの調査は現在、参加に対して開かれており、以前の調査とは異なり、コードを除くすべてをカバーしています:キャリア、職場だけでなく、健康、趣味などもあります。

CSSグリッドは、複雑で応答性の高いWebレイアウトを作成するための強力なツールです。設計を簡素化し、アクセシビリティを向上させ、古い方法よりも多くの制御を提供します。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

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

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

Dreamweaver Mac版
ビジュアル Web 開発ツール
