本文致力于猜测著名的开源库Googletest的主要框架,即“记录函数、执行所有测试”功能的实现。作者只是粗略浏览了Googletest的源码,所以只能给出一个可能的框架。下面以代码来描述Googletest的主要框架。
//MyTest.h
#pragma once
#include <stddef.h>
#include <stdio.h>
#include <vector>
class TestBase
{
public:
int Run();
private:
virtual void Body()=0;
};
class UnitTest
{
public:
static UnitTest* GetInstance();
void Register(TestBase*);
int Run();
static void DeleteInstance();
private:
UnitTest()=default;
static UnitTest* core;
std::vector<TestBase*> All_Test;
};
inline int RUN_ALL_TESTS() { return UnitTest::GetInstance()->Run(); }
#define Test_Class_Name(suite_name,test_name) \
Test_##suite_name##_##test_name
#define Test(suite_name,test_name) \
class Test_Class_Name(suite_name,test_name) : TestBase \
{ \
public: \
Test_Class_Name(suite_name,test_name)() \
{ \
UnitTest::GetInstance()->Register(this); \
} \
private: \
void Body() override; \
} \
Object_####suite_name##_##test_name; \
void Test_Class_Name(suite_name,test_name)::Body()
核心类UnitTest记录需要测试的函数,源码似乎使用了Singleton,所以这里也模仿使用Singleton。
一个关键的猜测是测试函数被封装成类,类的对象在实例化时执行注册,即让UnitTest记录这个类的指针。
//MyTest.cc
#include "MyTest.h"
int TestBase::Run()
{
printf("Some Wrap\n");
Body();
return 0;
}
UnitTest* UnitTest::GetInstance()
{
if (core==nullptr)
{
core = new UnitTest();
}
return core;
}
void UnitTest::DeleteInstance()
{
if (core!=nullptr)
{
delete core;
}
}
void UnitTest::Register(TestBase* p)
{
All_Test.push_back(p);
}
int UnitTest::Run()
{
for (size_t i=0; i<All_Test.size(); ++i)
{
printf("Test %llu\n", i+1);
int err = All_Test[i]->Run();
if(err)
return err;
}
return 0;
}
UnitTest* UnitTest::core = nullptr;
最后是主函数所在源文件。
//main.cc
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include "MyTest.h"
Test(First, easy)
{
printf("First work\n");
}
Test(Second, difficult)
{
printf("Second work\n");
}
int main()
{
return RUN_ALL_TESTS();
}
运行输出结果为
Test 1
Some Wrap
First work
Test 2
Some Wrap
Second work
而Googletest源码应用中,main函数应如下定义。
int main()
{
testing::InitGoogleTest();
return RUN_ALL_TESTS();
}
或者不实现main函数,改为链接libgtest_main.a.