下面的代码模仿gtest实现,主要说明了以下两点:
ASSERT_*
和EXPECT_*
系列断言的原理和作用.- gtest是怎样通过宏自动注册测试代码让其自动运行的.
1 #include <iostream> 2 #include <string> 3 #include <memory> 4 #include <vector> 5 6 7 #define ASSERT_EQ(a,b) if((a) != (b)) \ 8 { \ 9 std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \ 10 return; \ 11 } else { \ 12 std::cout<<"[ OK ] "<<std::endl; \ 13 } 14 15 #define ASSERT_NE(a,b) if((a) == (b)) \ 16 { \ 17 std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \ 18 return; \ 19 } else { \ 20 std::cout<<"[ OK ] "<<std::endl; \ 21 } 22 23 #define EXPECT_EQ(a,b) if((a) != (b)) \ 24 { \ 25 std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \ 26 } else { \ 27 std::cout<<"[ OK ] "<<std::endl; \ 28 } 29 30 #define EXPECT_NE(a,b) if((a) == (b)) \ 31 { \ 32 std::cout<<"[ FAIL ] "<<#a<<" not equal "<<#b<<std::endl; \ 33 } else { \ 34 std::cout<<"[ OK ] "<<std::endl; \ 35 } 36 37 #define MAKE_CLASS_NAME(test_case_name, test_name) MAKI_CLASS_NAME_I(test_case_name, test_name) 38 #define MAKI_CLASS_NAME_I(test_case_name, test_name) XTest_##test_case_name##_##test_name##_Test 39 #define XTEST_TEST(test_case_name,test_name) class MAKE_CLASS_NAME(test_case_name, test_name): \ 40 public ::xtest::Test { \ 41 public: \ 42 MAKE_CLASS_NAME(test_case_name, test_name)(): ::xtest::Test(#test_case_name, #test_name) \ 43 { \ 44 ::xtest::UnitTest::regist(std::shared_ptr<::xtest::Test>(this)); \ 45 } \ 46 virtual void testBody(); \ 47 static MAKE_CLASS_NAME(test_case_name, test_name) * instance; \ 48 }; \ 49 MAKE_CLASS_NAME(test_case_name, test_name) * MAKE_CLASS_NAME(test_case_name, test_name) ::instance \ 50 = new MAKE_CLASS_NAME(test_case_name, test_name) ();\ 51 void MAKE_CLASS_NAME(test_case_name, test_name)::testBody() 52 53 #define TEST(test_case_name, test_name) XTEST_TEST(test_case_name, test_name) 54 55 56 namespace xtest { 57 58 class Test{ 59 friend class UnitTest; 60 public: 61 Test(const std::string &n1, const std::string& n2):test_case_name(n1), test_name(n2){ 62 } 63 virtual void testBody() = 0; 64 std::string test_case_name; 65 std::string test_name; 66 private: 67 Test(const Test&) = delete; 68 Test& operator=(const Test&) = delete; 69 }; 70 71 class UnitTest { 72 public: 73 static UnitTest* getInstance(); 74 void Run(); 75 static void regist(std::shared_ptr<Test> const& a); 76 private: 77 static UnitTest* instance; 78 std::vector<std::shared_ptr<Test>> all_tests12; 79 }; 80 } 81 82 inline void RUN_ALL_TESTS(){ 83 xtest::UnitTest::getInstance()->Run(); 84 }
1 #include "xtest.h" 2 namespace xtest{ 3 4 UnitTest* UnitTest::instance = NULL; 5 UnitTest* UnitTest::getInstance(){ 6 if(instance == NULL){ 7 instance = new UnitTest(); 8 } 9 return instance; 10 } 11 void UnitTest::Run(){ 12 std::cout<<"[==========] Start XTest..."<<std::endl; 13 for(auto i = begin(all_tests12); i!= end(all_tests12); ++i){ 14 std::cout<<"[ RUN ] "<<(*i)->test_case_name<<"."<<(*i)->test_name<<std::endl; 15 (*i)->testBody(); 16 std::cout<<std::endl; 17 } 18 } 19 void UnitTest::regist(std::shared_ptr<Test>const& a){ 20 getInstance()->all_tests12.push_back(a); 21 } 22 }
现在看看怎么用吧
1 #include "xtest.h" 2 3 TEST(t1,t2){ 4 ASSERT_EQ(1,1); 5 ASSERT_EQ(1,2); 6 ASSERT_EQ(2,3); 7 } 8 TEST(t3,t4){ 9 EXPECT_EQ(1,1); 10 EXPECT_EQ(1,2); 11 EXPECT_EQ(2,3); 12 } 13 int main(int argc, char* argv[]) { 14 15 RUN_ALL_TESTS(); 16 return 0; 17 }
输出结果:
1 [==========] Start XTest... 2 [ RUN ] t1.t2 3 [ OK ] 4 [ FAIL ] 1 not equal 2 5 6 [ RUN ] t3.t4 7 [ OK ] 8 [ FAIL ] 1 not equal 2 9 [ FAIL ] 2 not equal 3