zoukankan      html  css  js  c++  java
  • Gtest源码剖析:1.实现一个超级简单的测试框架xtest

    下面的代码模仿gtest实现,主要说明了以下两点:

    1. ASSERT_* 和 EXPECT_*系列断言的原理和作用.
    2. 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
  • 相关阅读:
    C#异步编程:多线程基础Thread类
    WPF:TextBox控件禁用中文输入
    C#:泛型的协变和逆变
    C#:泛型接口
    C#:泛型委托
    C#:泛型类
    Jetbrains Rider:缺少.NET Framework 4.5.2
    C#:泛型方法
    C#:泛型
    C#:接口
  • 原文地址:https://www.cnblogs.com/xusd-null/p/3770432.html
Copyright © 2011-2022 走看看