Microsoft Unit Testing Framework for C++
阿新 • • 發佈:2018-11-19
Author: kagula
Date: 2018-05-11
這種情況只發生在“測試驅動”編碼方式中,現實世界我很少用到,這裡只是為了大致有個瞭解。
Step1:新建我們的第一個測試單元UnitTest1,新建solution
Visual C++ -> Test -> Native Unit Test Project
Step2:
用下面的程式碼替代建立的預設模板
Step3:
使用選單項[test]->[Run]->[All Tests]或則直接使用快捷鍵Ctrl+R+A
而不是習慣的F5或Ctrl+F5,之後會出現Test Explorer子視窗,如下圖。
Step2:為專案新增Unit Test依賴的標頭檔案和庫檔案搜尋路徑.
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\VS\UnitTest\include
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\VS\UnitTest\lib
Step3:
使用下面的步驟新增unit test檔案
Solution Explorer -> Add -> New Item -> C++ Unit Test.
把專案的Configuration Type屬性從原來的Application (.exe)改為Dynamic Library (.dll)
否則你單元測試程式碼是不能正常執行的。
Step5:
使用Ctrl+R+A執行所有的單元測試,或使用主選單項
Test->Run->All->Tests選單命令執行所有單元測試。
接下來你可以探索Test Explorer窗口裡的unit test功能的。
Final Step:
[1]
如果你專案unit test沒問題了,再把project的Configuration Type屬性 改回Application (.exe)。
[2]
如果改回EXE後,Ctrl+F5執行程式,console一閃而過,使用下面的設定
Configuration Properties -> Linker -> System -> SubSystem -> Console(/SUBSYSTEM:CONSOLE)
三、對已存dll專案的測試
Step1:新建個空白專案,當作是我們待測的現存dll專案。
Installed -> Visual C++ -> General -> Empty Project
新起專案名稱為UnitTest3
Configuration Type 設為 Dynamic Library(.dll)
這樣編譯原始碼後會生成dll lib等兩個檔案.
Step 2:
在當前solution下新建單元測試專案
Visual C++ -> Test -> Native Unit Test Project
我把project起名為MyUnitTester。
A 因為在Visual Studio 中 Debug方式執行,console會一閃而過.
https://docs.microsoft.com/en-us/visualstudio/test/how-to-use-microsoft-test-framework-for-cpp
[2]<<Microsoft.VisualStudio.TestTools.CppUnitTestFramework API Reference>>
https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts
Date: 2018-05-11
Introduction
VC自帶多個VC++單元測試工具,其中Microsoft Unit Testing Framework原生支援Test Explorer, 這裡通過三個例子來學習Microsoft Unit Testing Framework.Environment
[1]Visual Studio 2017, update 7.1Content
一、最簡單的測試這種情況只發生在“測試驅動”編碼方式中,現實世界我很少用到,這裡只是為了大致有個瞭解。
Step1:新建我們的第一個測試單元UnitTest1,新建solution
Visual C++ -> Test -> Native Unit Test Project
Step2:
用下面的程式碼替代建立的預設模板
unittest1.cpp
#include "stdafx.h" #include "CppUnitTest.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; #include <iostream> using namespace std; TEST_MODULE_INITIALIZE(ModuleInitialize) { Logger::WriteMessage("In Module Initialize"); } TEST_MODULE_CLEANUP(ModuleCleanup) { Logger::WriteMessage("In Module Cleanup"); } /* 第一次執行本unit test, 使用Ctrl+R+A 執行全部測試. 以後你可以在Test Explorer視窗中執行指定的測試函式. */ namespace KagulaUnitTest { //模擬我的第一個待測試的function集合 TEST_CLASS(myFirstFunctionSetForTest) { public: TEST_METHOD(TestMethod1) { //執行unit test不會開啟控制檯視窗, 所以你也不會看到下面這條程式碼的任何std輸出. cout << "hello,World!" << endl; } TEST_METHOD(TestMethod2) { //模擬耗時的操作. for (size_t i = 0; i < 1000; i++) { if ((i % 100) == 0) { //VisualStudio2017Update7.1有個很嚴重的缺陷,有時候,你改了程式碼,但是使用Test Explorer中的"Run selected Tests"選單項, //執行的還是老的程式碼, 這時候, 你得rebuild solution後再執行. //所以修改程式碼後, 修改下面的字串輸出, 從output視窗中檢視是不是修改已經生效很重要. Logger::WriteMessage("d."); } }//for }//test method };//test class //模擬我的第二個待測試的function集合 TEST_CLASS(mySecondFunctionSetForTest) { public: //Assert的具體用法參考下面的地址 //https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts TEST_METHOD(TestMethod2_1) { Logger::WriteMessage("TestMethod2_1"); int expected = 0; int actual = 0; Assert::AreEqual(expected, actual); Assert::AreEqual(expected, actual, L"are not equal assert!"); } TEST_METHOD(TestMethod2_2) { Logger::WriteMessage("TestMethod2_2"); Assert::Fail(L"Fail"); } }; }
Step3:
使用選單項[test]->[Run]->[All Tests]或則直接使用快捷鍵Ctrl+R+A
而不是習慣的F5或Ctrl+F5,之後會出現Test Explorer子視窗,如下圖。
Output子視窗,Show output from下拉框選項改為Tests,然後你就可以看到單元測試專案的輸出。
Step1:
建個簡單的console程式c++專案,用來模擬已經存在的EXE程式專案我寫了個很簡單的程式碼Source.cpp
#include <iostream> using namespace std; //這個函式用來演示你寫的函式如何被"單元測試"工具呼叫 int myFunction() { return 1; } int main(int argc, char* argv[]) { cout << "hello, World!" << endl; return 0; }
Step2:為專案新增Unit Test依賴的標頭檔案和庫檔案搜尋路徑.
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\VS\UnitTest\include
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\VS\UnitTest\lib
Step3:
使用下面的步驟新增unit test檔案
Solution Explorer -> Add -> New Item -> C++ Unit Test.
如果沒有“C++ Unit Test”模板,就添加個普通的cpp檔案
Test.cpp
//若不需要單元測試,把UNIT_TEST巨集註釋掉就可以了!
//否則exe程式會去找我們不需要的unit test依賴的dll.
#define UNIT_TEST
#ifdef UNIT_TEST
#include <CppUnitTest.h>
//假設這是我待做unit test測試的函式.begin
extern int myFunction();
//假設這是我待做unit test測試的函式.end
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
BEGIN_TEST_MODULE_ATTRIBUTE()
TEST_MODULE_ATTRIBUTE(L"Date", L"2010/6/12")
END_TEST_MODULE_ATTRIBUTE()
TEST_MODULE_INITIALIZE(ModuleInitialize)
{
Logger::WriteMessage("In Module Initialize");
}
TEST_MODULE_CLEANUP(ModuleCleanup)
{
Logger::WriteMessage("In Module Cleanup");
}
/*
第一次執行本unit test, 使用Ctrl+R+A 執行全部測試.
以後你可以在Test Explorer視窗中執行指定的測試函式.
*/
namespace KagulaUnitTest
{
TEST_CLASS(myFunctionSetForTest)
{
public:
//Assert的具體用法參考下面的地址
//https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts
TEST_METHOD(TestMethod2_1)
{
Logger::WriteMessage("TestMethod1");
int expected = 0;
int actual = myFunction();
Assert::AreEqual(expected, actual, L"are not equal assert!");
}
};
}
#endif
Step4:
把專案的Configuration Type屬性從原來的Application (.exe)改為Dynamic Library (.dll)
否則你單元測試程式碼是不能正常執行的。
Step5:
使用Ctrl+R+A執行所有的單元測試,或使用主選單項
Test->Run->All->Tests選單命令執行所有單元測試。
接下來你可以探索Test Explorer窗口裡的unit test功能的。
Final Step:
[1]
如果你專案unit test沒問題了,再把project的Configuration Type屬性 改回Application (.exe)。
[2]
如果改回EXE後,Ctrl+F5執行程式,console一閃而過,使用下面的設定
Configuration Properties -> Linker -> System -> SubSystem -> Console(/SUBSYSTEM:CONSOLE)
三、對已存dll專案的測試
Step1:新建個空白專案,當作是我們待測的現存dll專案。
Installed -> Visual C++ -> General -> Empty Project
新起專案名稱為UnitTest3
Configuration Type 設為 Dynamic Library(.dll)
這樣編譯原始碼後會生成dll lib等兩個檔案.
我這個專案,由兩個原檔案組成,原始碼內容如下
CDemoLib.h
#ifndef _LIB_H_
#define _LIB_H_
#ifdef _WIN32
#ifdef _WINDLL //VC2017新建專案後,改生成方式為dll, 會自帶這個巨集定義.
#define LIB_API extern "C" __declspec(dllexport)
#else
#define LIB_API extern "C" __declspec(dllimport)
#endif
//我不喜歡編寫非C語言風格的介面供呼叫者使用, 除非時間緊.
#ifdef _WINDLL
#define CLASS_EXPORT __declspec(dllexport)
#else
#define CLASS_EXPORT __declspec(dllimport)
#endif
#else
//非Windows環境不需要那麼麻煩直接定一個空白的就可以了.
#define LIB_API
#endif
LIB_API int add(int x, int y);
class CLASS_EXPORT MyDemoClass
{
public:
int add(int a, int b);
};
#endif
CDemoLib.cpp
#include "CDemoLib.h"
int add(int x, int y)
{
return x + y;
}
int MyDemoClass::add(int a, int b)
{
return a + b;
}
Step 2:
在當前solution下新建單元測試專案
Visual C++ -> Test -> Native Unit Test Project
我把project起名為MyUnitTester。
這個專案只有一個原始檔,清單如下:
#include "stdafx.h"
#include "CppUnitTest.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#include "../UnitTest3/CDemoLib.h"
//新增All Configuration 庫檔案搜尋路徑: $(SolutionDir)$(Configuration);
#pragma comment(lib, "UnitTest3.lib")
namespace MyUnitTester
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
Logger::WriteMessage("MyUnitTester....");
int expect = 0;
int actual = add(0, 0);
//C風格介面 測試
Assert::AreEqual(expect, actual, L"are not equal assert!");
MyDemoClass mdc;
actual = mdc.add(0, 0);
//C++風格介面 測試
Assert::AreEqual(expect, actual, L"are not equal assert!");
}
};
}
Final Step:
然後你就可以Ctrl+R+A執行單元測試了。
Remark:
Q: 為什麼不用boost.test?A 因為在Visual Studio 中 Debug方式執行,console會一閃而過.
Reference
[1]<<Use the Microsoft Unit Testing Framework for C++ in Visual Studio>>https://docs.microsoft.com/en-us/visualstudio/test/how-to-use-microsoft-test-framework-for-cpp
[2]<<Microsoft.VisualStudio.TestTools.CppUnitTestFramework API Reference>>
https://docs.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference#general_asserts