gtest学习笔记--7 构造自己的单元测试框架

本篇文章与之前的文章不属于同一个项目,另外新开的项目。
配置是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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值