UnitTest関連記事
やりたいこと
C++で作成したDLLがエクスポートしている関数の単体テスト(UnitTest)を行いたい。
概要
VisualStudio(2017)で単体テストプロジェクトを作成し、そこで単体テストを行う。
やること
プロジェクト作成
DLL作成用のプロジェクトを含むソリューションに、単体テスト用プロジェクトを追加する。
テスト対象のdllの必要物を参照設定する
C++で作成したDLLをC++で呼ぶでやったように、テストしたいDLLを使えるようにする。
(.libが見えるようにリンカの設定をし、DllImportをするための.hが見えるようにインクルードフォルダの設定をする)
単体テスト用コードを作成
初期状態で、下記のようなコードが作成される。
#include "stdafx.h"
#include "CppUnitTest.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest1
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
// TODO: テスト コードをここに挿入します
}
};
}
ここに、以前作成したDLLを呼ぶコードを追加する。
(もとのDLLはこちらを参照)※単体テスト用に関数をいくつか追加。
DLLの関数を、下記のようにテストコードで呼び出す。
#include "stdafx.h"
#include "CppUnitTest.h"
#include "DllTest.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTestCpp
{
TEST_CLASS(UnitTest1)
{
public:
BEGIN_TEST_METHOD_ATTRIBUTE(TestMethod_Normal)
TEST_PRIORITY(1)
END_TEST_METHOD_ATTRIBUTE()
TEST_METHOD(TestMethod_Normal)
{
wchar_t* buf_in = L"あいうえお";
wchar_t* buf_out = nullptr;
int ans1 = Test_MyApiAdd(1, 2);
int ans2 = Test_MyApiSub(3, 1);
Test_MyApiPointerCopy(buf_in, &buf_out);
Assert::AreEqual(ans1, 1 + 2); // 正常に終了
Assert::AreEqual(ans2, 3 - 1); // 正常に終了
Assert::IsNotNull(buf_out); // 正常に終了
Logger::WriteMessage("Test OK");// デバッグ時のログ(出力欄)に出力
}
BEGIN_TEST_METHOD_ATTRIBUTE(TestMethod_Error)
TEST_PRIORITY(1)
END_TEST_METHOD_ATTRIBUTE()
TEST_METHOD(TestMethod_Error)
{
wchar_t* buf_in = nullptr;
wchar_t* buf_out = nullptr;
int ans1 = Test_MyApiAdd(1, 2);
int ans2 = Test_MyApiSub(3, 1);
Test_MyApiPointerCopy(buf_in, &buf_out);
Assert::AreEqual(ans1, 1 + 5); // ans1と1+5が一致しないので、ここでTestストップ。
Assert::AreEqual(ans2, 100 - 1); // 実施されない
Assert::IsNotNull(buf_out); // 実施されない
Logger::WriteMessage("Test OK");
}
};
}
DLLの関数のコードは今回はこんな感じ。
足し算、引き算、文字列へのポインタをコピーする、だけの関数。
int __cdecl Test_MyApiAdd(int p1, int p2)
{
return p1 + p2;
}
int __cdecl Test_MyApiSub(int p1, int p2)
{
return p1 - p2;
}
void __cdecl Test_MyApiPointerCopy(wchar_t* p_in, wchar_t** p_out)
{
if (p_in != nullptr)
{
*p_out = p_in;
}
else
{
p_out = nullptr;
}
}
Assert
「Assert::AreEqual()」などのモジュールを使って、テスト対象の関数の戻り値などが正しい値かどうかを確認する。下記のようなものがある。
モジュール名 | 役目 |
---|---|
AreEqual | オブジェクトが一致することを確認する |
AreNotEqual | オブジェクトが一致しないことを確認する |
IsNull | オブジェクトがNULLであることを確認する |
IsNotNull | オブジェクトがNULLでないことを確認する |
など。ほかにも多数ある。 |
詳しくは、MSのページを参照。
Attribute
テスト用メソッドに対して、Attributeを設定できるらしいが、どうやって使うかはっきりわからず。詳しくは、MSのページを参照。
VisualStudio上でUnitTestを実施
[テスト] > [実行] の中のメニューを選んで、UnitTestを実施する。
または、[テスト] > [ウインドウ] > [テストエクスプローラ] でテストエクスプローラを開き、そこでもテストの実行ができる。
[実行]ではなく、[デバッグ]をすると、UnitTestのコード上でBreakを貼ったり、step実行ができる。
コンソールでUnitTestを実施
必要物をダウンロード
テストエージェントvstest.console.exe
が必要。下記の「VisualStudio2019のツール」からダウンロードする。
https://visualstudio.microsoft.com/ja/downloads/?q=agents
コンソールで実施
インストール後、「VSTest.Console.exe 」を使用して、テストを行う。
書式は、
vstest.console.exe "UnitTestのプロジェクトが吐いたDLL" "オプション"
rem Unitテスト実施用bat
rem x86用 ログを出力
rem ログは、「カレントディレクトリ\TestResults」に出力される
cd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\"
vstest.console.exe "C:\Users\masa\Documents\myTortoiseGit\WPF-\020_CppDllProject\Debug\UnitTestCpp.dll" /platform:x86 /inIsolation /Logger:trx
pause
※注意※
上のbatでは、vstest.console.exeのあるフォルダとしてC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\
としているが、VisualStudioを入れずに上のダウンロードからVSTESTのエージェントだけを入れた場合は、フォルダが別になる。その場合は、パスを自分のPCにあったものにすること。
例)私のPCの場合は下記にあった。
C:\Program Files (x86)\Microsoft Visual Studio\2019\TestAgent\Common7\IDE\Extensions\TestPlatform\vstest.console.exe
ログは、カレントディレクトリにできた「TestResults」フォルダ内に保存される。
.trxファイルを開くと、VisualStudioで結果を見ることができる。
※BEGIN_TEST_METHOD_ATTRIBUTEで設定したTEST_PRIORITYの値は、この結果で見れるっぽい。vstestの実行パラメータに、優先順位を指定できるので、そこに生きると思われる。(未検証)
C#のUnitTestについて
C++とほとんど同じやり方でUnitTestできる。下記のページを参照。
MsTestによるユニットテストの解説
https://qiita.com/mima_ita/items/55394bcc851eb8b6dc24
VSの設定からプロジェクトの設定、コードの書き方まで詳しく書いてくれている。
これ見れば一通りできそう。(コマンドラインでの実施も書いてくれている)
MS docs
公式ページ。単体テストのやり方はいくつかあるらしく(MSTestとか、xUnitとか)、その説明が書かれたページ。
MSTestのコマンドラインパラメータの一覧
参照(C++)
Visual StudioでC ++用のMicrosoft単体テストフレームワークを使用する
Microsoft.VisualStudio.TestTools.CppUnitTestFramework APIリファレンス(Assertとか、Attributeとか)
https://docs.microsoft.com/ja-jp/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference?view=vs-2019#cppUnitTestAssert_h