コンテンツへスキップ
Angularで単体テストを実行する方法

Angularで単体テストを実行する方法

Angularで単体テストを行う方法、Angularでサービスをモックする方法などについては、このAngular単体テストのチュートリアルで学習します。

9min read

ほとんどの開発チームは、Angularでのユニットテストには時間がかかることに同意し、多くの開発チームも不要であることに同意し、スキップすることを決定するでしょう。プロジェクトの規模とそれに取り組む人々のプログラミングスキルによっては、Angularアプリをテストしないことが正しいことかもしれません。しかし、一般的に、ユニットテストは、設計が不十分なコードベースを作成して、後ではるかにコストのかかるデバッグやコード修正につながるのを避けるために、非常に価値があります。では、コードの品質を危険にさらすのと、開発中のコードを事前に理解し、開発サイクルの早い段階でコードのバグを見つけるのを助けるのとどちらがいいのでしょうか?

私が言いたいのは、特に大規模なAngularアプリ、ビッグデータ、またはデータサイエンスプロジェクトに取り組む場合は、単体テストを過小評価しないでください。

Try Ignite UI for Angular

全体像: ユニットテストとは?

ソフトウェア開発では、単体テスト (分離テストとも呼ばれます) は、アプリが正常に動作していることを確認し、開発フェーズでコードの個別のユニットのバグを排除するために実行されます。単体テストを複数回実行して、異なる入力セットに対する特定のコード単位の動作を検証できます。

欠損値のキャッチなどの問題や、「フィルター関数は正しい方法で値を絞り込んでいるか」などの問題、またはデータ サイエンス アプリの「関数の戻り値は期待どおりの形状を持っているか」などのより複雑な問題に取り組んでいます。

ユニットテストが必要な理由について、私は次のように考えています。

  • 単体テストを実行すると、バグをすぐに検出して修正できるため、コードを書き直すのにコストと時間がかかるアプリ開発サイクルのかなり後のフェーズで予期しない出力を回避できます。
  • コードの特定のユニットから予想される動作がわかれば、何が壊れているかを確認できるため、コードをより簡単に更新できます。
  • 単体テストを実行すると、コードの品質に自信が持てるようになり、コードをより適切に構造化するのに役立ちます。
  • 個々のクラスを個別にテストし、アプリ内の結合ブロックの強度をテストして、それらがどのように動作するかを確認できます。
  • ユニットテストではリファクタリングが可能で、すべてがどのように機能するかをすでに知っているため、動作を変更することなくバグのない方法でコードを変更できます。
  • これはコードの分離されたユニットで実行されるため、新しく追加された機能やファイルの変更をテストするときはいつでも、ユニット テストを実行してもコード全体が壊れないことが保証されます。
  • ユニットテストは超高速で、すべてのエラー条件をシミュレートできます。
  • ネットワークやサービスの停止、データ認証エラーなどの偶発的な理由で失敗することはありません。
  • いわゆるエクストリームプログラミングの方法論で非常に便利で、基本的に壊れる可能性のあるすべてのものをテストするように求められます。
  • 単元が提供する機能とその使用方法を学習する場合は、単体テストを使用して単元の API の基本を理解できます。

Angularでのユニットテストとは何ですか?

Angularでの単体テストは、誤動作する関数や正しくないロジックなどの問題をできるだけ早く特定することを目標に、個々のコード単位をテストするプロセスです。また、Angularプロジェクトはデフォルトでモジュール化されているため、このようなアプリで単体テストを実行すると、アプリの機能を単独で調べることができるため、少し直感的に感じられます。

他のフレームワークとは異なり、Angularはモデルの単体テストを実行するための優れた方法を提供します。通常、開発者は手動テストを行って動作を確認し、コードが機能しているかどうかを確認します。ただし、場合によっては、すべての小さな変更を手動でテストすると、単体テストの開発に比べて時間がかかります。しかし、Angularは、ユニットテストを行うツールと Karmaのようなテストランナーを提供します。

Angularアプリをテストする必要がある理由

Angularコードベースを機能ごとにテストすることは、コードの品質を向上させ、本番環境でのバグやデッドコードを減らし、メンテナンスコストを削減し、コード全体を壊す不一致なしに迅速なリファクタリングやアップグレードを実現するための最良の方法です。

最初は遅いように見えるかもしれませんが、長い目で見れば報われます。バグは開発全体で発見されます。デバッグプロセスが改善されました。特定のテストが失敗した場合、期待どおりに機能していないものを正確に簡単に見つけることができます。また、特にテスト駆動開発と単体テストは、実際よりも少し難しそうに聞こえるため、新しいツールやベスト プラクティスに頼ることで、プロセス全体を実際に促進し、自動化することができます。

AngularでのユニットテストとテストAngularコンポーネントのテスト

コンポーネントでできることはいくつかあり、コンポーネントのテストを作成する際には、これらすべての動作が考慮されていることを確認する必要があります。

  • テンプレートを HTML DOM ツリーにレンダリングできます。
  • 入力を使用して親コンポーネントからデータを受け取り、出力を使用してデータを出力できます。
  • さまざまな種類のイベントと対話できます。
  • 彼らはサービスや店舗と話すことができます。
  • データをバインドして、ユーザーが編集できるようにすることができます。

次のセクションでは、Angularコンポーネントとテスト コンポーネントで単体テストを行う方法を示します。

We will start testing Angular components, using Ignite UI for Angular. Here’s what to do.

Set up TestBed

Angularでは、テスト用のTestBedを提供しており、コンポーネントやサービスを簡単にテストできる環境を整えています。これは通常のAngularモジュールのように構成され、宣言されたすべてのコンポーネントがコンパイルされます。各テストで重複したコードを保存するために、beforeEach 関数で使用できます。

Angular 単体テストでのテストベッドの設定 コードスニペット

コンポーネントがコンパイルされた後、HTML DOM でレンダリングされるコンポーネントを作成できます。コンポーネントをテスト環境で使用する場合、更新時に自動的に再レンダリングされません。そのため、手動でトリガーする必要があります。

    fixture.detectChanges(); 

DOM のテスト

ほとんどの場合、コンポーネント内の関数は、テンプレートを反映したロジックを実行しています。DOM ツリーには、DebugElement とそのメソッド query と queryAll を使用してアクセスできます。

  • クエリは、条件に一致する最初の要素を返します
  • queryAll は、一致する要素のコレクションを返します

By.css() を使用すると、CSS セレクターで要素を取得できます。

testing the dom in angular unit testing code screenshot

トリガー イベント ハンドラー

フォームデータを送信し、特定のボタンをクリックしたときにトリガーされる関数があると想像してください。テストでは、2つの選択肢があります。1 つ目は関数を直接実行すること、2 つ目は、そのボタンのクリック イベントをシミュレートすることです。これは、DebugElement の triggerEventHandler を使用して簡単に行うことができます。これには、イベントの名前とイベントのプロパティの 2 つの引数があります。

Angular Unit Testing でのイベントのトリガー

イベントが必要な場合は、new キーワードを使用して作成し、null ではなくパラメーターとして send する必要があります。

偽の依存関係を使用してデータを「モック」する方法

ほとんどの場合、特定のコードを分離してテストします。しかし、コンポーネントは多くの異なるサービスと通信し、各サービスには独自の依存関係があるため、1 つの機能をテストするためだけにすべての依存関係を追加すると複雑になります (また、コードが不必要に長くなります)。

代わりに、包括的なIgnite UIツールキットを使用してAngular、実際の依存関係の動作をシミュレートする偽の依存関係を作成できます。この方法はモックと呼ばれます。

Using Jasmine spies

Jasmineは、スパイと呼ばれる偽の依存関係を作成するための優れた機能を提供します。例を挙げましょう。

using jasmine spies in angular unit testing

DataService から fetchData を呼び出すメソッドを持つ 1 つの単純なコンポーネントがあり、API にリクエストを送信してデータを取得し、その後、応答がある場合はこのデータをコンポーネントに保存します。 この場合、fetchData 関数で何が起こっているかをテストしたくありません。私たちが気にしているのは、レスポンスです。したがって、ここではspyOnメソッドを使用して応答を偽造し、このメソッドがトリガーされたかどうかを確認できます。

Angularユニットテストでデータを取得する方法のスクリーンショット

非同期コードとAngularオブザーバブルをテストする方法

非同期コードのテストは似ていますが、わずかな違いがあります。

Angularスクリーンショットコードでの単体テストでの非同期コードのテスト

非同期のメソッドをスパイオンしたい場合は、 .returnValues() の代わりに .resolveTo() を使用します。その後、非同期メソッドをテストする場合は、さらに2つのことを行います。まず、テストを fakeAsync でラップし、次に tick() を使用して非同期の時間の経過をシミュレートします。

テンプレートに表示するAngular ObservableとBehaviorSubjectからのデータをテストする場合も同様です。サブジェクトに .next を代入し、tick() を使用してしばらく待ってから次の行に処理する必要があります。

testing asynchronous method in unit testing in angular screenshot code

コードカバレッジの測定

コードカバレッジは、コードのどの部分が単体テストでテストされるかを示す指標です。まだテストされていないアプリケーションの部分を検出します。コードを書くときは、全体的なカバレッジスコアが減るのではなく、増えるようにする必要があります。80%のコードカバレッジが目指すべきコード目標であることは認められています。ただし、できるだけ多くのコードをカバーするようにしてください。多ければ多いほど良いです。カバレッジレポートを提供する組み込みコマンドがあります。テストコマンドに–code-coverageフラグを追加するだけです。

ng test –コードカバレッジ

Angular Unit Testingのコードカバレッジを測定する スクリーンショットコード

ngテンプレートの組み込みコードカバレッジジェネレーターを使用したくない場合は、他にも何千ものnpmパッケージから選択できます。また、開発にAzure DevOpsを使用している場合は、私たちが使用できる組み込み機能もあります。

最後に、Angularユニットテストのベストプラクティスは何ですか

最後に、Angularユニットテストを実行する際に採用できるベストプラクティスをいくつか紹介したいと思います。

  • コマンドラインから ng test を実行してAngular Unit テストのコンパイルと実行を開始し、Testing モジュールが適切に設定されていることを確認します。
  • ユニットテストには、ユニットがテストされる方法、シナリオを説明するなど、適切なAngularで名前を付けます。
  • 単体テストを高速かつスムーズに実行できるように、関数をできるだけ小さく構築します。
  • 単体テストは常に分離された環境で実行し、外部依存関係を排除します。
  • サービスをテストするときは、依存関係に Jasmine フレームワークのスパイを使用します。
  • コンポーネントのテスト時に nativeElement を呼び出すのではなく、debugElement を使用して DOM にアクセスする (プライマリランタイム環境の抽象化を提供) ことをお勧めします。
  • サーバーでアプリを実行する場合は、queryselector の代わりに By.css を使用してください。これは、queryselector はブラウザーでのみ機能するためです。
  • コード カバレッジが 80% 以上であることを確認してください。
Ignite UI for Angular

デモを予約