クイック スタート: テスト エクスプローラーによるテスト駆動開発
変更を繰り返して段階的に開発を行ううえで、コードの正しい動作を維持するには、単体テストを作成することをお勧めします。サード パーティ製を含めていくつかのフレームワークを単体テストの記述に使用できます。一部のテスト フレームワークは、別々の言語またはプラットフォームでのテストに特化されています。テスト エクスプローラーは、1 つのインターフェイスで、どのフレームワークでの単体テストにも対応します。最も一般的に使用されるフレームワーク用にアダプターが用意されており、他のフレームワーク用に独自のアダプターを作成することもできます。
テスト エクスプローラーは、Visual Studio の以前のエディションにあった単体テスト ウィンドウに代わる機能です。これには次のような利点があります。
.NET、アンマネージ、データベース、およびその他の種類のテストを 1 つのインターフェイスで実行できます。
NUnit や MSTest など、任意の単体テスト フレームワークを使用できます。
必要な情報をすべて、1 つのウィンドウで確認できます。
テスト エクスプローラーの使用
テスト エクスプローラーを使用して単体テストを実行するには
任意のテスト フレームワークを使用して単体テストを作成します。
たとえば、MSTest フレームワークを使用するテストを作成するには:
テスト プロジェクトを作成します。
[新しいプロジェクト] ダイアログ ボックスで、[Visual Basic]、[Visual C#]、または [Visual C++] を展開し、[テスト] をクリックします。
[単体テスト プロジェクト] を選択します。
各単体テストをメソッドとして記述します。各テスト メソッドにプレフィックスとして [TestMethod] 属性を付けます。
メニュー バーで、[テスト]、[単体テストの実行]、[すべてのテスト] の順にクリックします。
ソリューションがビルドされ、テストが実行されます。
テスト エクスプローラーが開き、結果の概要が表示されます。
テストの一覧を表示するには: 任意のカテゴリで、[すべて表示] をクリックします。
概要に戻るには、[ホーム] ビューをクリックします。
テスト結果の詳細を表示するには: 例外メッセージなどの詳細を詳細ペインに表示するには、テスト エクスプローラーでテストを選択します。
テストのコードに移動するには: テスト エクスプローラーでテストをダブルクリックするか、ショートカット メニューの [テストを開く] をクリックします。
テストをデバッグするには: 1 つ以上のテストを選択し、ショートカット メニューの [選択したテストのデバッグ] をクリックします。
重要 |
---|
最新のテスト実行の結果が表示されます。色分けされた結果バーに表示されるのは、実行されたテストの結果のみです。たとえば、複数のテストを実行してそのいくつかに失敗し、次に成功したテストのみを実行した場合は、結果バーには緑色のみが表示されます。 |
[!メモ]
テストが表示されない場合は、使用するテスト フレームワークにテスト エクスプローラーを接続するためのアダプターがインストールされていることを確認してください。詳細については、「テスト エクスプローラーでさまざまなテスト フレームワークを使用する」を参照してください。
チュートリアル: 単体テストを使用してメソッドを開発する
このチュートリアルでは、Microsoft 単体テスト フレームワークを使用して、テスト済みメソッドを C# で開発する方法を示します。他の言語に適合させることも、NUnit など他のテスト フレームワークを使用することも、容易です。詳細については、「さまざまなテスト フレームワークを使用する」を参照してください。
テストとメソッドを作成する
Visual C# クラス ライブラリ プロジェクトを作成します。このプロジェクトには、提供するコードを含めます。この例では、MyMath という名前が付いています。
テスト プロジェクトを作成します。
[新しいプロジェクト] ダイアログ ボックスで、[Visual C#]、[テスト]、[単体テスト プロジェクト] の順にクリックします。
基本的なテスト メソッドを記述します。特定の入力に対して生じた結果を確認します。
[TestMethod] public void BasicRooterTest() { // Create an instance to test: Rooter rooter = new Rooter(); // Define a test input and output value: double expectedResult = 2.0; double input = expectedResult * expectedResult; // Run the method under test: double actualResult = rooter.SquareRoot(input); // Verify the result: Assert.AreEqual(expectedResult, actualResult, delta: expectedResult / 100); }
テストからメソッドを生成します。
Rooter にカーソルを置き、ショートカット メニューで [生成]、[新しい型] の順にクリックします。
[新しい型の生成] ダイアログ ボックスで、[プロジェクト] をクラス ライブラリ プロジェクトに設定します。この例では、MyMath です。
SquareRoot にカーソルを置き、ショートカット メニューで [生成]、[メソッド スタブ] の順にクリックします。
単体テストを実行します。
[テスト] メニューで、[単体テストの実行]、[すべてのテスト] の順にクリックします。
ソリューションがビルドされ、実行されます。
テスト エクスプローラーが開き、結果が表示されます。
[失敗したテスト] の下にテストが表示されます。
テストの名前を選択します。
テストの詳細は、テスト エクスプローラーの下部に表示されます。
テストに失敗した箇所を確認するには、[スタック トレース] の下に表示されている項目を選択します。
この時点で、テストとスタブが作成されています。テストに合格するには、これらを修正する必要があります。
各変更後にすべてのテストに合格する
MyMath\Rooter.cs で、SquareRoot のコードを改善します。
public double SquareRoot(double input) { return input / 2; }
テスト エクスプローラーで [すべて実行] をクリックします。
テストがビルドされ、テストが実行されます。
テストに合格します。
テストを追加して入力の範囲を拡張する
あらゆる場合にコードが動作するという信頼性を強化するには、テストを追加して、より広範囲の入力値を試みます。
ヒント 合格した既存のテストは変更しないでください。代わりに、新しいテストを追加します。既存のテストを変更するのは、ユーザー要件が変更されたときのみに限定します。このポリシーにより、コードを拡張する作業において既存の機能が失われる状況を回避できます。
一定範囲の入力値を試みるために、次のテストをテスト クラスに追加します。
[TestMethod] public void RooterValueRange() { // Create an instance to test: Rooter rooter = new Rooter(); // Try a range of values: for (double expectedResult = 1e-8; expectedResult < 1e+8; expectedResult = expectedResult * 3.2) { RooterOneValue(rooter, expectedResult); } } private void RooterOneValue(Rooter rooter, double expectedResult) { double input = expectedResult * expectedResult; double actualResult = rooter.SquareRoot(input); Assert.AreEqual(expectedResult, actualResult, delta: expectedResult / 1000); }
テスト エクスプローラーで [すべて実行] をクリックします。
最初のテストには今回も合格しますが、新しいテストには失敗します。
エラー箇所を見つけるには、失敗したテストを選択し、テスト エクスプローラーの下部で、[スタック トレース] の下に表示されている先頭の項目を選択します。
テスト対象のメソッドを調べて、問題点を確認します。MyMath.Rooter クラスで、コードの記述を変更します。
public double SquareRoot(double input) { double result = input; double previousResult = -input; while (Math.Abs(previousResult - result) > result / 1000) { previousResult = result; result = result - (result * result - input) / (2 * result); } return result; }
テスト エクスプローラーで [すべて実行] をクリックします。
今回は、両方のテストに合格します。
例外的なケース用にテストを追加する
負数の入力用にテストを追加します。
[TestMethod] public void RooterTestNegativeInputx() { Rooter rooter = new Rooter(); try { rooter.SquareRoot(-10); } catch (ArgumentOutOfRangeException e) { return; } Assert.Fail(); }
テスト エクスプローラーで [すべて実行] をクリックします。
テスト対象のメソッドはループするため、実行を手動で取り消す必要があります。
[キャンセル] をクリックします。
テストが 10 秒後に停止します。
メソッドのコードを修正します。
public double SquareRoot(double input) { if (input <= 0.0) { throw new ArgumentOutOfRangeException(); } ...
テスト エクスプローラーで [すべて実行] をクリックします。
すべてのテストに合格します。
テストを変更せずにリファクタリングする
テストを変更せずに、コードを簡略化します。
ヒント リファクタリングとは、コードのパフォーマンスを高めたり、コードをわかりやすくすることを目的として行う変更です。コードの動作を変更することを意図しないため、テストは変更されません。
リファクタリングの手順は、機能を拡張する手順とは別に実行することをお勧めします。テストを変更しないことで、リファクタリング時に誤ってバグが生じる状況を回避できます。
public class Rooter { public double SquareRoot(double input) { if (input <= 0.0) { throw new ArgumentOutOfRangeException(); } double result = input; double previousResult = -input; while (Math.Abs(previousResult - result) > result / 1000) { previousResult = result; result = (result + input / result) / 2; //was: result = result - (result * result - input) / (2*result); } return result; } }
[すべて実行] をクリックします。
今回もすべてのテストに合格します。