本篇文章与之前的文章不属于同一个项目,另外新开的项目。
配置是W10、vs2015 release x64平台的 MT模式下。编码为多字节编码。
先放结果图吧。
参考的文档在test.cpp里面的置顶。
TestCase.h
#pragma once
class TestCase
{
public:
TestCase(const char* case_name) :testcase_name(case_name) {};
//执行测试案例
virtual void Run() = 0;
//测试案例的结果
int nTestResult;
//测试案列名称
const char* testcase_name;
};
UnitTest.h
#pragma once
#include <vector>
#include <iostream>
#include <windows.h>
#include "TestCase.h"
/*
设置颜色
https://www.cnblogs.com/mingguzhou/p/12802441.html
*/
void SetColor(unsigned short forecolor = 4, unsigned short backgroudcolor = 0)
{
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); //获取缓冲区句柄
SetConsoleTextAttribute(hCon, forecolor | backgroudcolor); //设置文本及背景色
}
class UnitTest
{
public:
//获取单例
static UnitTest* GetInstance();
//注册测试案例
TestCase* RegisterTestCase(TestCase* testcase);
//执行
int Run();
//记录当前执行的测试案例
TestCase* currentTestCase;
//总的执行结果
int nTestResult;
//通过案例
int nPassed;
//失败案例
int nFailed;
protected:
//案例集合
std::vector<TestCase*> testcases_;
};
UnitTest* UnitTest::GetInstance()
{
static UnitTest instance;
return &instance;
}
TestCase* UnitTest::RegisterTestCase(TestCase* testcase)
{
testcases_.push_back(testcase);
return testcase;
}
int UnitTest::Run()
{
nTestResult = 0;
for (std::vector<TestCase*>::iterator it=testcases_.begin();
it!=testcases_.end();++it)
{
TestCase* testcase = *it;
currentTestCase = testcase;
//绿色
SetColor(FOREGROUND_GREEN|FOREGROUND_GREEN);
std::cout << "==================================="<<std::endl;
std::cout << "Run TestCase:" << testcase->testcase_name << std::endl;
testcase->Run();
SetColor(FOREGROUND_GREEN | FOREGROUND_GREEN);
std::cout << "End TestCase:" << testcase->testcase_name << std::endl;
//此处在断言宏里面修改了nTestResult
if (testcase->nTestResult)
{
nFailed++;
}
else
{
nPassed++;
}
nTestResult ++;
}
SetColor(FOREGROUND_GREEN | FOREGROUND_GREEN);
std::cout << "======================================" << std::endl;
std::cout << "Total TestCase : " << nPassed + nFailed << std::endl;
std::cout << "Passed : " << nPassed << std::endl;
//红色
SetColor(FOREGROUND_INTENSITY|FOREGROUND_RED);
std::cout<< "Failed : " << nFailed << std::endl;
return nTestResult;
}
nancytest.h
#pragma once
#include "TestCase.h"
#include "UnitTest.h"
#include <iostream>
/*
个人理解: 把每个宏当做一个函数比较好理解
//##的作用在于(token-pasting)符号连接操作符,即将宏定义的多个形参成一个实际参数名,在这里testcase_name_TEST
*/
#define TESTCASE_NAME(testcase_name)\
testcase_name##_TEST
///NANCY_TEST_
/// 以下这段宏定义掩盖了繁杂的测试用例封装过程
///写宏定义的时候中间不要穿插,注释,空行。
/*
类静态成员在类内声明,类外定义,
类型名 + 限定字+类名+类作用域(::)+变量名
#号的作用是(stringizing)字符串化操作符。其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串。("testcase_name").
注意Run()后边没有{},之所以这么做是宏定义将测试用例放入到Run的方法主体里。例如
NTEST(FooTest_PassDemo)
{
EXPECT_EQ(3, Foo(1, 2));
EXPECT_EQ(2, Foo(1, 1));
}
上述代码中EXPECT_EQ(2, Foo(1, 1));代码放入到Run的方法主体里。
*/
#define NANCY_TEST_(testcase_name)\
class TESTCASE_NAME(testcase_name):public TestCase\
{\
public:\
TESTCASE_NAME(testcase_name)(const char* case_name):TestCase(case_name){};\
virtual void Run();\
private:\
static TestCase* const testcase_;\
};\
TestCase* const TESTCASE_NAME(testcase_name)\
::testcase_=UnitTest::GetInstance()->RegisterTestCase(\
new TESTCASE_NAME(testcase_name)(#testcase_name));\
void TESTCASE_NAME(testcase_name)::Run()
///NTEST宏
#define NTEST(testcase_name)\
NANCY_TEST_(testcase_name)
///RUN_ALL_TEST宏
#define RUN_ALL_TESTS()\
UnitTest::GetInstance()->Run();
///断言的宏EXPECT_EQ
#define EXPECT_EQ(m,n)\
if(m!=n)\
{\
UnitTest::GetInstance()->currentTestCase->nTestResult=1;\
SetColor(FOREGROUND_INTENSITY|FOREGROUND_RED);\
std::cout<< "Failed" << std::endl; \
std::cout<< "Expect:" << m << std::endl; \
std::cout<< "Actual:" << n << std::endl; \
}
test.cpp
#include "nancytest.h"
/*
在window平台下,去除了打印的字体颜色
参考
https://www.cnblogs.com/Leo_wl/archive/2012/07/25/2608916.html
https://www.cnblogs.com/salomon/archive/2012/07/25/2608667.html
https://blog.csdn.net/csdn_kou/article/details/80748467
https://www.cnblogs.com/kernel0815/p/3619361.html
https://www.cnblogs.com/mingguzhou/p/12802441.html
https://blog.csdn.net/s9434/article/details/79871598?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param
*/
int Foo(int a, int b)
{
return a + b;
}
NTEST(FooTest_PassDemo)
{
EXPECT_EQ(3, Foo(1, 2));
EXPECT_EQ(2, Foo(1, 1));
}
NTEST(FooTest_FailDemo)
{
EXPECT_EQ(3, Foo(1, 2));
EXPECT_EQ(2, Foo(1, 2));
}
int main(int argc, char* argv[])
{
RUN_ALL_TESTS();
system("pause");
return 0;
}