二、了解gtest的实现原理
代码参考:GitHub - zchrissirhcz/cpp-moments: Records of learning/practising C++
1、断言的实现
断言的可以用宏定义实现
#define MyTEST_EXPECT(x, y, cond) \
if (!((x)cond(y))) \
{ \
printf("%s:%u: Failure\n", __FILE__, __LINE__); \
if (strcmp(#cond, "==") == 0) \
{ \
printf("Expected equality of these values:\n"); \
printf(" %s\n", #x); \
qtest_evaluate_if_required(#x, x); \
printf(" %s\n", #y); \
qtest_evaluate_if_required(#y, y); \
} \
else \
{ \
printf("Expected: (%s) %s (%s), actual: %s vs %s\n", #x, #cond, #y, std::to_string(x).c_str(), std::to_string(y).c_str()); \
} \
}
template<typename T>
void qtest_evaluate_if_required(const char* str, T value)
{
if (strcmp(str, std::to_string(value).c_str()) != 0)
{
std::cout << " Which is: " << value << std::endl;
}
}
#define EXPECT_EQ(x, y) MyTEST_EXPECT(x, y, ==)
#define EXPECT_NE(x, y) MyTEST_EXPECT(x, y, !=)
#define EXPECT_LT(x, y) MyTEST_EXPECT(x, y, <)
#define EXPECT_LE(x, y) MyTEST_EXPECT(x, y, <=)
#define EXPECT_GT(x, y) MyTEST_EXPECT(x, y, >)
#define EXPECT_GE(x, y) MyTEST_EXPECT(x, y, >=)
#define EXPECT_TRUE(x) \
if (!((x))) \
{ \
printf("%s:%u: Failure\n", __FILE__, __LINE__); \
printf("Value of: %s\n", #x); \
printf(" Actual: false\n"); \
printf("Expected: true\n"); \
}
#define EXPECT_FALSE(x) \
if (((x))) \
{ \
printf("%s:%u: Failure\n", __FILE__, __LINE__); \
printf("Value of: %s\n", #x); \
printf(" Actual: true\n"); \
printf("Expected: false\n"); \
}
2、TEST功能的实现
用静态类的add方法将测试用例添加到map中
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
test_suite_name##_##test_name##_Test
#define GTEST_MARK_CLASS_NAME_(test_suite_name, test_name) \
test_suite_name##_##test_name##_Mark
#define STR(R) #R
#define GTEST_TEST(test_suite_name, test_name) \
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
: public testParent { \
public: \
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default; \
private: \
void TestBody(); \
}; \
int GTEST_MARK_CLASS_NAME_(test_suite_name, test_name) = TestEntity::get_instance().addTest(#test_suite_name, new GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)); \
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
#define MyTEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
静态类的写法
class testParent
{
public:
virtual void TestBody(){}
};
class TestEntity
{
public:
TestEntity(){}
static TestEntity& get_instance(){
static TestEntity defaultTestEntity;
return defaultTestEntity;
}
int addTest(string suitname, testParent* p){
test_sets[suitname].push_back(p);
return 0;
}
void run_all_test_functions(){
for(std::map<std::string, std::vector<testParent*> >::iterator miter = test_sets.begin(); miter != test_sets.end(); ++miter){
std::cout<< "Now run the suitcase:\t" << miter->first << endl;
for(std::vector<testParent*>::iterator viter = miter->second.begin(); viter != miter->second.end(); ++viter){
(*viter) -> TestBody();
}
}
}
private:
std::map<std::string, std::vector<testParent*> > test_sets; // suitname
};
本质思想就是创建一个静态类TestEntity,在宏定义展开TEST时会生成一个全局变量int,这个int的生成调用静态类的add方法将测试用例添加到map中。