Edited at

【C++】UnitTest(C ++用Microsoft単体テストフレームワーク/vstest.Console.exe)の使い方概要


やりたいこと

C++で作成したDLLがエクスポートしている関数の単体テスト(UnitTest)を行いたい。


概要

VisualStudio(2017)で単体テストプロジェクトを作成し、そこで単体テストを行う。


やること


プロジェクト作成

DLL作成用のプロジェクトを含むソリューションに、単体テスト用プロジェクトを追加する。

image.png

image.png


テスト対象のdllの必要物を参照設定する

C++で作成したDLLをC++で呼ぶでやったように、テストしたいDLLを使えるようにする。

(.libが見えるようにリンカの設定をし、DllImportをするための.hが見えるようにインクルードフォルダの設定をする)


単体テスト用コードを作成

初期状態で、下記のようなコードが作成される。


unittest1.cpp

#include "stdafx.h"

#include "CppUnitTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest1
{
TEST_CLASS(UnitTest1)
{
public:

TEST_METHOD(TestMethod1)
{
// TODO: テスト コードをここに挿入します
}

};
}


ここに、以前作成したDLLを呼ぶコードを追加する。

(もとのDLLはこちらを参照)※単体テスト用に関数をいくつか追加。


DLLの関数を、下記のようにテストコードで呼び出す。


unittest1.cpp

#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の関数のコードは今回はこんな感じ。

足し算、引き算、文字列へのポインタをコピーする、だけの関数。


DllTest.cpp


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を実施する。

または、[テスト] > [ウインドウ] > [テストエクスプローラ] でテストエクスプローラを開き、そこでもテストの実行ができる。

image.png

[実行]ではなく、[デバッグ]をすると、UnitTestのコード上でBreakを貼ったり、step実行ができる。


コンソールでUnitTestを実施

「VSTest.Console.exe 」を使用して、テストを行う。

書式は、

vstest.console.exe "UnitTestのプロジェクトが吐いたDLL" "オプション"


UnitTest用.bat

rem Unitテスト実施用bat

rem x86用 ログを出力
rem ログは、「カレントディレクトリ\TestResults」に出力される
cd "C:\Program Files (x86)\Microsoft Visual Studio\2017\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

実行すると、このような窓が表示される。

image.png

ログは、カレントディレクトリにできた「TestResults」フォルダ内に保存される。

.trxファイルを開くと、VisualStudioで結果を見ることができる。

image.png

※BEGIN_TEST_METHOD_ATTRIBUTEで設定したTEST_PRIORITYの値は、この結果で見れるっぽい。vstestの実行パラメータに、優先順位を指定できるので、そこに生きると思われる。(未検証)


C#のUnitTestについて

C++とほとんど同じやり方でUnitTestできる。下記のページを参照。


MsTestによるユニットテストの解説

https://qiita.com/mima_ita/items/55394bcc851eb8b6dc24

VSの設定からプロジェクトの設定、コードの書き方まで詳しく書いてくれている。

これ見れば一通りできそう。(コマンドラインでの実施も書いてくれている)


MS docs

公式ページ。単体テストのやり方はいくつかあるらしく(MSTestとか、xUnitとか)、その説明が書かれたページ。

https://docs.microsoft.com/ja-jp/visualstudio/test/walkthrough-creating-and-running-unit-tests-for-managed-code?view=vs-2017


参照(C++)

Visual StudioでC ++用のMicrosoft単体テストフレームワークを使用する

https://docs.microsoft.com/ja-jp/visualstudio/test/how-to-use-microsoft-test-framework-for-cpp?view=vs-2019

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