テスト エクスプローラーを使用したネイティブ コードの単体テスト
Visual Studio では、C++ で記述されているアンマネージ コードの単体テストできます。 アンマネージ コードは、ネイティブ コードと呼ばれます。
次の手順は、起動する必要な情報が含まれています。 後半のセクションでは、手順を詳しく説明するチュートリアルを紹介します。
アンマネージ コード DLL 用の単体テストを作成するには
テストの他の Visual Studio でプロジェクトを作成するために [ネイティブ テスト プロジェクト] テンプレートを使用します。
テスト プロジェクトはサンプル コードが含まれています。
DLL をテストにアクセスできるようにする:
#include DLL の外部アクセス可能な関数の宣言を含む .h ファイル。
.h ファイルは _declspec(dllimport)でマークされている関数宣言を含める必要があります。 また、DEF ファイルを使ったメソッドをエクスポートできます。 詳細については、「Importing and Exporting from a DLL」を参照してください。
単体テストはテスト対象の DLL からエクスポートされる関数にのみアクセスできます。
テスト プロジェクトの参照が DLL のプロジェクトを追加する:
テスト プロジェクトの [プロパティ] で、[共通プロパティ]、[Framework と参照] を展開し、[参照の追加] をクリックします。
テスト プロジェクトで、テスト クラスとテスト メソッドをテスト マクロを使用して作成し、そのクラスを次のようにアサートする:
#include "stdafx.h" #include <CppUnitTest.h> #include "..\MyProjectUnderTest\MyCodeUnderTest.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; TEST_CLASS(TestClassName) { public: TEST_METHOD(TestMethodName) { // Run a function under test here. Assert::AreEqual(expectedValue, actualValue, L"message", LINE_INFO()); } }
Assert は テストの結果を確認するために使用できるさまざまな静的関数が含まれています。
LINE_INFO() パラメーターは省略できます。 PDB ファイルがない場合は、テスト ランナーのエラーの位置を特定できるようになります。
また、テストの設定、およびクリーンアップ メソッドを記述できます。 詳細については、TEST_METHOD マクロの定義を開き、CppUnitTest.h のコメントを読み取ります。
テスト クラスを入れ子にすることはできません。
テストを実行するためにテスト エクスプローラーを使用する:
[表示] メニューで、[その他のウィンドウ]、[テスト エクスプローラー] の順にクリックします。
Visual Studio ソリューションをビルドします。
テスト エクスプローラーで [すべて実行] をクリックします。
テストをテスト エクスプローラーで詳しく調査するには:
エラー メッセージおよびスタック トレースなどの詳細を参照するには、テスト名を選択します。
エラーの場所またはテスト コードに進むにテスト名 (たとえば) をダブルクリックして開きます。
テストのショートカット メニューで、デバッガーのテストを実行するに [選択されたテストのデバッグ] をクリックします。
チュートリアル: テスト エクスプローラーによるアンマネージ DLL の開発
独自の DLL を開発するには、このチュートリアルを調整できます。 主な手順は次のとおりです。:
ネイティブ テスト プロジェクトを作成します。 テストは、DLL とは別のプロジェクトで開発すると作成されます。
DLL のプロジェクトを作成します。 このチュートリアルでは、新しい DLL を作成しても、既存の DLL をテストする手順は似ています。
DLL 関数をテストに参照できるようにします。
テストを繰り返し増やしてください。 これは、コードの開発とテストでガイド「Red」緑リファクタリングのサイクルをお勧めします。
失敗したテストのデバッグ。 デバッグ モードでテストできます。
テストを変えずリファクタリング。 リファクタリングは外部動作を変更せずにコードの構造の改良を意味します。 コードのパフォーマンス、拡張、または読みやすさが向上するようにできます。 目的の動作を変更することはないため、コードのリファクタリングの変更を行っている最中にテストは変更されません。 テストはリファクタリング中、バグがないことを確認します。 したがって、テストがない場合は、よりも多くの自信をもつこのような変更を加えることができます。
カバレッジを確認します。 単体テストでは、コードの多くを実行する場合に便利です。 コードのどの部分をテストで使用されたかを検出できます。
外部リソースから分離単位。 通常、DLL は、そのほかの DLL など、データベースを開発している、またはリモート システム サブシステムの他のコンポーネントに依存しています。 依存関係の分離の各単位をテストする場合に便利です。 外部コンポーネントは、テストの実行速度を設定できます。 開発時に、他のコンポーネントが不完全である可能性があります。
ネイティブ単体テスト プロジェクトを作成する
[ファイル] メニューで、[新規]、[プロジェクト] をクリックします。
ダイアログ ボックスで、[インストール済み]、[テンプレート]、[Visual C++]、[テスト] を展開します。
[ネイティブ テスト プロジェクト] テンプレートを選択します。
このチュートリアルでは、テスト プロジェクトが NativeRooterTestという名前です。
新しいプロジェクトでは、unittest1.cppをチェックします。
次の点に注意してください。
各テストは TEST_METHOD(YourTestName){...}を使用して定義されます。
従来の関数シグネチャを記述する必要はありません。 シグネチャは TEST_METHOD マクロによって作成されます。 マクロは、void インスタンスの関数を生成します。 また、静的関数は、テスト メソッドに関する情報を生成します。 この情報は、テスト エクスプローラーにメソッドを探すことができます。
テスト メソッドがクラスに TEST_CLASS(YourClassName){...}を使用してグループ化されます。
テストの実行時、各テスト クラスのインスタンスが作成されます。 テスト メソッドは、不定の順序で呼び出されます。 各モジュール、クラス、またはメソッドの前後に呼び出される特殊なメソッドを定義できます。 詳細については、「組織 C++ テスト」を参照してください。
テスト エクスプローラーでテストを実行できることを確認する:
テスト コードを挿入する:
TEST_METHOD(TestMethod1) { Assert::AreEqual(1,1); }
Assert クラスがテスト メソッドの結果を確認するために使用できるさまざまな静的メソッドを提供することに注意してください。
[テスト] メニューで、[すべてのテスト(A)][実行 ] をクリックします。
テストのビルドと実行。
テスト エクスプローラーが表示されます。
テストは [成功したテスト数] の下に表示されます。
アンマネージ DLL プロジェクトを作成する
[Win32 プロジェクト] のテンプレートを使用して [Visual C++] のプロジェクトを作成します。
このチュートリアルでは、プロジェクトは RootFinderという名前です。
Win32 アプリケーション ウィザードの [シンボルのエクスポート][DLL] を選択します。
[シンボルのエクスポート] オプションがエクスポートしたメソッドを宣言するために使用できる便利なマクロを生成します。
プリンシパル .h ファイルのエクスポート関数を宣言する:
宣言子 __declspec(dllexport) はクラスのパブリック メンバーとプロテクト メンバーを DLL の外側に表示される。 詳細については、「C++ クラスでの dllimport と dllexport の使用」を参照してください。
プリンシパル .cpp ファイルで、関数の最小の本体を追加する:
// Find the square root of a number. double CRootFinder::SquareRoot(double v) { return 0.0; }
DLL プロジェクトにテスト プロジェクトを結合する
テスト プロジェクトのプロジェクト参照に DLL のプロジェクトを追加する:
テスト プロジェクトのプロパティを開き、[Framework と参照][共通プロパティ] をクリックします。
[新しい参照の追加] をクリックします。
[参照の追加] ダイアログ ボックスで、DLL のプロジェクトを選択し、[追加] をクリックします。
主な単体テスト .cpp ファイルで、DLL コードの .h ファイルを格納する:
#include "..\RootFinder\RootFinder.h"
エクスポート関数を使用する基本的なテストを追加する:
TEST_METHOD(BasicTest) { CRootFinder rooter; Assert::AreEqual( // Expected value: 0.0, // Actual value: rooter.SquareRoot(0.0), // Tolerance: 0.01, // Message: L"Basic test failed", // Line number - used if there is no PDB file: LINE_INFO()); }
ソリューションをビルドします。
新しいテストがテスト エクスプローラーに表示されます。
テスト エクスプローラーで [すべて実行] をクリックします。
コード プロジェクトの関数を実行するテストを実行できることをテストおよびコード プロジェクトと検証した設定されます。 ここで実際のテスト、およびコードの記述を開始できます。
テストを繰り返し増やして成功させる
新しいテストの追加:
TEST_METHOD(RangeTest) { CRootFinder rooter; for (double v = 1e-6; v < 1e6; v = v * 3.2) { double actual = rooter.SquareRoot(v*v); Assert::AreEqual(v, actual, v/1000); } }
ヒント
これは、合格したテストを変更しないことをお勧めします。代わりに、新しいテストを追加して、コードをテスト成功更新し、別のテストなど) を追加します。
ユーザーが要件を変更する場合は、正しいテストを無効にしてください。新しいテストを記述して同じインクリメンタル方法で、一度に一つずつ表示します。
次に、テスト エクスプローラーでソリューションを選択し、[すべて実行] をクリックしますビルドします。
新しいテストが失敗します。
ヒント
これを記述した直後に各テストが失敗することを検証します。これは、失敗してテストを記述する簡単な誤りを防ぐことができます。
新しいテスト成功ようにテスト対象コードを拡張する:
#include <math.h> ... double CRootFinder::SquareRoot(double v) { double result = v; double diff = v; while (diff > result/1000) { double oldResult = result; result = result - (result*result - v)/(2*result); diff = abs (oldResult - result); } return result; }
次に、テスト エクスプローラーで、ソリューションを [すべて実行] をクリックしますビルドします。
両方のテストが成功します。
ヒント
テストを一つずつ追加してコードを開発します。すべてのテストを反復処理するたびに成功することを確認します。
失敗したテストをデバッグする
別のテストを追加する:
#include <stdexcept> ... // Verify that negative inputs throw an exception. TEST_METHOD(NegativeRangeTest) { wchar_t message[200]; CRootFinder rooter; for (double v = -0.1; v > -3.0; v = v - 0.5) { try { // Should raise an exception: double result = rooter.SquareRoot(v); _swprintf(message, L"No exception for input %g", v); Assert::Fail(message, LINE_INFO()); } catch (std::out_of_range ex) { continue; // Correct exception. } catch (...) { _swprintf(message, L"Incorrect exception for %g", v); Assert::Fail(message, LINE_INFO()); } } }
ソリューションをビルドし、[すべて実行] をクリックします。
(またはダブルクリック) 失敗したテストを開きます。
アサーションが強調表示されます。 エラー メッセージは、テスト エクスプローラーの詳細ペインに表示されます。
テストが失敗したかを参照するには、関数をステップ実行する:
SquareRoot 関数の先頭にブレークポイントを設定します。
失敗したテストのショートカット メニューで、[選択したテストのデバッグ(D)] をクリックします。
ブレークポイントで実行が停止したときに、コードをステップ実行します。
配置する関数にコードを挿入する:
#include <stdexcept> ... double CRootFinder::SquareRoot(double v) { // Validate parameter: if (v < 0.0) { throw std::out_of_range("Can't do square roots of negatives"); }
すべてのテストで渡します。
テストを変更せずにコードをリファクタリングする
SquareRoot 関数を中央の計算を簡略化する:
// old code: // result = result - (result*result - v)/(2*result); // new code: result = (result + v/result)/2.0;
ソリューションをビルドし、エラーが生じないように、[すべて実行] をクリックします。
ヒント
コードを変更するときにバグが生じないこと適切なセットの単体テストは全体を示します。
他の変更とは別にリファクタリングを保持します。
次のステップ
分離ほとんどの DLL はデータベースなどの他のサブシステムやそのほかの DLL に依存します。 これらのコンポーネントは、同時に作成されます。 他のコンポーネントがまだ利用できないで単体テストを実行するように、またはサンプルに置き換える必要があります
**ビルド確認テスト。**指定した間隔でチームのビルド サーバーで実行するテストを指定できます。 これは、一部のチーム メンバーの作業を統合するときにバグがもたらされないことを確認します。
**チェックイン テスト。**あるテストがソース管理に各チーム メンバーのチェック コードの前に実行されることを必須とすることができます。 通常、ビルド確認テストの完全なセットのサブセットです。
また、コード カバレッジの最小を義務付けていることができます。
参照
処理手順
チュートリアル: ダイナミック リンク ライブラリの作成と使用 (C++)