unit-testing
すべての言語の単体テストの一般的な規則
サーチ…
前書き
ユニットテストを開始するときには、あらゆる種類の質問が出てくる:
ユニットテストとは何ですか? SetUpとTearDownとは何ですか?依存関係をどのように扱うのですか?なぜ単体テストを行うのですか?良い単体テストを作るにはどうすればいいですか?
この記事ではこれらすべての質問に答えるので、好きな言語で単体テストを始めることができます。
備考
単体テストとは何ですか?
単体テストは、実行するタスクを確実に実行するためのコードのテストです。クラスの個々のメソッドである可能な最も低いレベルでコードをテストします。
ユニットとは何ですか?
孤立してテストできるコードの個別のモジュール。ほとんどの時間クラスとそのメソッド。このクラスは、一般に「テスト中のクラス」(CUT)または「テスト中のシステム」(SUT)と呼ばれ、
ユニットテストとインテグレーションテストの違い
単体テストは、単一のクラスを実際に依存するものから完全に分離して単独でテストする行為です。統合テストは、1つまたは複数の実際の依存関係とともに1つのクラスをテストする行為です。
SetUpとTearDown
作成されるとSetUpメソッドはすべてのユニットテストの前に実行され、TearDownはすべてのテストの後に実行されます。
一般的には、TearDownのSetUpとすべてのクリーンアップステップに必要なすべてのステップを追加します。しかし、これらの手順がすべてのテストに必要な場合にのみ、これらの方法を作成します。そうでない場合は、「アレンジ」セクションの特定のテストでこれらのステップを実行します。
依存関係の処理方法
多くの場合、クラスはメソッドを実行するために他のクラスの依存関係を持ちます。これらの他のクラスに依存できないようにするには、これらを偽造する必要があります。これらのクラスを自分で作成することも、独立またはモックアップフレームワークを使用することもできます。分離フレームワークは、偽のクラスを簡単に作成できるコードの集まりです。
偽のクラス
CUTに必要とされる依存性のふりをするのに十分な機能を提供するクラス。フェイクには、スタブとモックの2種類があります。
- スタブ(Stub):テストの合否に影響を及ぼさず、テストを実行できるだけの偽物。
- モック(Mock):CUTの動作を追跡し、その動作に基づいてテストを合格または不合格にする偽物。
ユニットテストはなぜですか?
1.ユニットテストでバグが見つかる
特定のクラスの期待動作が何であるかを定義する一連のテストを書くと、期待どおりに動作していないものが明らかになります。
2.単体テストはバグを遠ざける
バグを導入する変更を加えると、次回にテストを実行するときにテストで明らかにすることができます。
3.ユニットテストにより時間を節約する
単体テストを書くことは、コードが最初から正しく設計されていることを確実にするのに役立ちます。単体テストはコードが何をすべきかを定義します。したがって、してはならないことを行うコードを書く時間を費やすことはありません。誰もコードが動作しているとは思っていないとチェックし、自分が動作すると思うように何かをしなければなりません。ユニットテストを書く時間を費やしてください。
4.単体テストで安心
それらのテストをすべて実行して、コードが想定どおりに動作することを知ることができます。あなたのコードの状態を知っていること、それが機能していること、恐怖を感じずに更新して改善できることはとても良いことです。
ユニットテストは、クラスの適切な使用を文書化する
単体テストは、コードの仕組み、期待されること、テストするコードを使用する適切な方法の簡単な例になります。
単体テストの一般規則
1.単体テストの構造については、AAAルールに従ってください
アレンジ:
テストするものを設定します。テストと期待される結果を実行するための変数、フィールド、プロパティと似ています。
Act:実際にテストしているメソッドを呼び出す
アサート:
テストフレームワークを呼び出して、あなたの「行為」の結果が期待されたものであることを確認します。
2.孤立してその時にテストするもの
すべてのクラスは単独でテストする必要があります。彼らはモックやスタブ以外には依存してはいけません。彼らは他のテストの結果に依存すべきではありません。
3.単純な「真ん中を右に」テストを最初に書く
あなたが書いた最初のテストは、最も簡単なテストでなければなりません。彼らはあなたが書こうとしている機能を基本的かつ簡単に説明するものでなければなりません。そして、一度それらのテストが合格すれば、あなたのコードの境界と境界をテストするより複雑なテストを書くべきです。
エッジをテストするテストを書く
基本がテストされ、基本的な機能が動作することがわかったら、エッジをテストする必要があります。適切な一連のテストでは、特定のメソッドに何が起こる可能性があるかの外側のエッジを調べます。
例えば:
- オーバーフローが発生した場合はどうなりますか?
- 値がゼロ以下になるとどうなりますか?
- MaxIntやMinIntに行くとどうなりますか?
- 361度の円弧を作成するとどうなりますか?
- 空の文字列を渡すとどうなりますか?
- 文字列のサイズが2GBの場合はどうなりますか?
5.境界を越えたテスト
ユニットテストは、指定された境界の両側をテストする必要があります。境界をまたいだ移動は、コードが予測できない方法で失敗したり実行されたりする場所です。
6.できる場合は、スペクトル全体をテストします
実用的であれば、機能性の可能性をすべてテストしてください。列挙型が含まれている場合は、列挙内のすべての項目を使用して機能をテストします。すべての可能性をテストすることは実用的ではないかもしれませんが、すべての可能性をテストできる場合は実行してください。
7.可能であれば、すべてのコードパスをカバーする
これは難しいことですが、コードがテスト用に設計されていて、コードカバレッジツールを使用している場合は、コードのすべての行が単体テストで少なくとも1回はカバーされるようにすることができます。すべてのコードパスをカバーしても、バグはありませんが、必ずしもすべてのコード行の状態に関する貴重な情報が得られます。
8.バグを明らかにするテストを作成し、修正します。
バグを見つけたら、それを明らかにするテストを書いてください。その後、バンは簡単にテストをデバッグしてバグを修正します。次に、何らかの理由でバグが戻ってきた場合、すぐにわかるように、良い回帰テストを行います。デバッガで簡単に直接テストを実行すると、バグを修正するのが簡単です。
ここでの利点は、テストをテストしたことです。テストが失敗したのを見て、それが通過したことを確認したら、テストは正常に動作していることが証明されています。これにより、これはさらに優れた回帰テストになります。
9.各テストを互いに独立させる
テストは決してお互いに依存すべきではありません。テストを特定の順序で実行する必要がある場合は、テストを変更する必要があります。
10.テストごとに1つのアサートを書く
テストごとに1つのアサートを書く必要があります。そうすることができない場合は、SetUpイベントとTearDownイベントを使用して環境を正しく作成し、各テストを個別に実行できるように、コードを屈折させます。
11.テストにはっきりと名前を付けます。長い名前を恐れないでください
テストごとに1つのアサーションを実行するので、各テストは非常に限定的になることがあります。したがって、長い、完全なテスト名を使用することを恐れないでください。
長い完全な名前は、どのテストが失敗したのか、テストが何をしようとしているのかをすぐに知ることができます。
長い、明確に名前が付けられたテストでも、テストを記録できます。 "DividedByZeroShouldThrowException"という名前のテストでは、ゼロで除算しようとしたときにコードの動作を正確に記録します。
12.発生したすべての例外が実際に発生したことをテストする
コードで例外が発生した場合は、実際に発生したすべての例外が想定されるときに確実に発生するようにテストを作成します。
13. CheckTrueまたはAssert.IsTrueの使用を避けます。
ブール条件のチェックは避けてください。たとえば、2つのものがCheckTrueまたはAssert.IsTrueと等しいかどうかを確認する場合は、代わりにCheckEqualsまたはAssert.IsEqualを使用します。どうして?このため:
CheckTrue(Expected、Actual)これは次のような報告をします: "いくつかのテストは失敗しました:期待されたものはTrueでしたが、実際の結果はFalseでした。
これは何も教えてくれません。
CheckEquals(期待、実際)
これはあなたに次のように伝えます:「いくつかのテストは失敗しました:7は期待されましたが、実際の結果は3でした」
期待値が実際にブール条件である場合にのみ、CheckTrueまたはAssert.IsTrueを使用してください。
14.テストを継続的に実行する
コードの作成中にテストを実行します。テストをすばやく実行して、マイナーな変更があってもテストを実行できるようにする必要があります。通常の開発プロセスの一環としてテストを実行できない場合、何かが間違っています。ユニットテストはほぼ即座に実行されるはずです。そうでない場合は、おそらくあなたがそれらを孤立して実行していないためです。
15.すべての自動ビルドの一部としてテストを実行する
開発中にテストを実行するのと同じように、継続的な統合プロセスの不可欠な部分である必要があります。失敗したテストは、ビルドが壊れていることを意味します。失敗したテストを残さないでください。それをビルドの失敗とみなし、すぐに修正してください。
C#での単純な単体テストの例
この例では、単純な電卓の合計方法をテストします。
この例では、ApplicationToTestというアプリケーションをテストします。このクラスにはCalcというクラスがあります。このクラスにはSum()メソッドがあります。
Sum()メソッドは次のようになります。
public void Sum(int a, int b)
{
return a + b;
}
このメソッドをテストする単体テストは次のようになります。
[Testclass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
//Arrange
ApplicationToTest.Calc ClassCalc = new ApplicationToTest.Calc();
int expectedResult = 5;
//Act
int result = ClassCalc.Sum(2,3);
//Assert
Assert.AreEqual(expectedResult, result);
}
}