Google Test源码浅析(一) -------- 基本使用

0. 引言

  Google Test是常用的一个开源测试框架,它的框架在测试过程中更加灵活,便捷,在后续演示实例的过程中会提到。源码可以参照https://github.com/google/googletest.git,本篇文章中介绍gtest的基本使用

1. TEST宏

  TEST宏是一个很重要的宏,它构成一个测试特例。TEST宏的第一个参数是“测试用例名”,第二个参数是“测试特例名”。测试用例(Test Case)是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序路径或核实是否满足某个特定需求,测试特例是测试用例下的一组测试。
  以下面代码为例,下面两个TEST宏构成的是一个测试用例——测试用例名是IsOdd(奇数方法检测,测试IsOdd函数),包含两组测试用例

#include <gtest/gtest.h>                                                                                                         

   //判断奇数还是偶数                                                                                                               
   bool IsOdd(int x)                                                                                                                
   {                                                                                                                                
     return x % 2 == 1;                                                                                                             
   }                                                                                                                                

  TEST(IsOddTest,odd1)                                                                                                                
  {                                                                                                                                
    ASSERT_TRUE(IsOdd(3));                                                                                                         
    ASSERT_TRUE(IsOdd(5));                                                                                                         
    ASSERT_TRUE(IsOdd(7));                                                                                                         
    ASSERT_TRUE(IsOdd(9));                                                                                                         
    ASSERT_TRUE(IsOdd(11));                                                                                                        
  }    
  TEST(IsOddTest,odd2)                                                                                                                 
  {                                                                                                                                
    ASSERT_FALSE(IsOdd(2));                                                                                                        
    ASSERT_FALSE(IsOdd(4));                                                                                                        
    ASSERT_FALSE(IsOdd(6));                                                                                                        
    ASSERT_FALSE(IsOdd(8));                                                                                                        
    ASSERT_FALSE(IsOdd(10));                                                                                                       
  }                

结果:

[root@VM_0_14_centos 1]# ./test 
Running main() from gtest_main.cc
[==========] Running 2 tests from 1 test case.//两组测试来源于一个测试用例
[----------] Global test environment set-up.
[----------] 2 tests from IsOddTest
[ RUN      ] IsOddTest.odd1
[       OK ] IsOddTest.odd1 (0 ms)//第一组
[ RUN      ] IsOddTest.odd2
[       OK ] IsOddTest.odd2 (0 ms)//第二组
[----------] 2 tests from IsOddTest (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (0 ms total)
[  PASSED  ] 2 tests.

2. 参数化设计

  还是上面判断奇数和偶数的例子;向上面写法自己使用宏来写,有时候测试用例的参数过多,这样写起来很麻烦;gtest里面提供了一个基类testing::TestWithParam< T >,使用者可以继承基类,通过TEST_ P来获取到参数,并且使用INSTANTIATE_TEST_CASE_P 来生成测试用例
 

 class IsOddTestTrueReturn : public testing::TestWithParam<int>//一个子类继承了gtest里面的类                                      
  {};                                                                                                                              

  //P是参数化的意思                                                                                                                
  TEST_P(IsOddTestTrueReturn,TrueReturn){//第一个是类名,第二个随便写                                                              

   int n = GetParam();//获取参数                                                                                                  
   EXPECT_TRUE(IsOdd(n));//将参数传入函数里面,进行测试                                                                           
  }     
//生成测试用例                                                                                                                  
INSTANTIATE_TEST_CASE_P(IsOdd,IsOddTestTrueReturn,testing::Values(1,3,5,7,9,11));    

class IsOddTestFalseReturn : public testing::TestWithParam<int>                                                                  
  {};                                                                                                                              

    TEST_P(IsOddTestFalseReturn, FalseReturn){                                                                                       
    int n = GetParam();                                                                                                            
    EXPECT_FALSE(IsOdd(n));                                                                                                        
 }                                                                                                                                
 INSTANTIATE_TEST_CASE_P(IsOdd,IsOddTestFalseReturn,testing::Values(2,4,6,8,10));                   

结果:

[root@VM_0_14_centos 1]# ./test 
Running main() from gtest_main.cc
[==========] Running 11 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 6 tests from IsOdd/IsOddTestTrueReturn//6个测试用例来源于类IsOddTestTrueReturn
[ RUN      ] IsOdd/IsOddTestTrueReturn.TrueReturn/0
[       OK ] IsOdd/IsOddTestTrueReturn.TrueReturn/0 (0 ms)
[ RUN      ] IsOdd/IsOddTestTrueReturn.TrueReturn/1
[       OK ] IsOdd/IsOddTestTrueReturn.TrueReturn/1 (0 ms)
[ RUN      ] IsOdd/IsOddTestTrueReturn.TrueReturn/2
[       OK ] IsOdd/IsOddTestTrueReturn.TrueReturn/2 (0 ms)
[ RUN      ] IsOdd/IsOddTestTrueReturn.TrueReturn/3
[       OK ] IsOdd/IsOddTestTrueReturn.TrueReturn/3 (0 ms)
[ RUN      ] IsOdd/IsOddTestTrueReturn.TrueReturn/4
[       OK ] IsOdd/IsOddTestTrueReturn.TrueReturn/4 (0 ms)
[ RUN      ] IsOdd/IsOddTestTrueReturn.TrueReturn/5
[       OK ] IsOdd/IsOddTestTrueReturn.TrueReturn/5 (0 ms)
[----------] 6 tests from IsOdd/IsOddTestTrueReturn (0 ms total)

[----------] 5 tests from IsOdd/IsOddTestFalseReturn//6个测试用例来源于IsOddTestFalseReturn
[ RUN      ] IsOdd/IsOddTestFalseReturn.FalseReturn/0
[       OK ] IsOdd/IsOddTestFalseReturn.FalseReturn/0 (0 ms)
[ RUN      ] IsOdd/IsOddTestFalseReturn.FalseReturn/1
[       OK ] IsOdd/IsOddTestFalseReturn.FalseReturn/1 (0 ms)
[ RUN      ] IsOdd/IsOddTestFalseReturn.FalseReturn/2
[       OK ] IsOdd/IsOddTestFalseReturn.FalseReturn/2 (0 ms)
[ RUN      ] IsOdd/IsOddTestFalseReturn.FalseReturn/3
[       OK ] IsOdd/IsOddTestFalseReturn.FalseReturn/3 (0 ms)
[ RUN      ] IsOdd/IsOddTestFalseReturn.FalseReturn/4
[       OK ] IsOdd/IsOddTestFalseReturn.FalseReturn/4 (0 ms)
[----------] 5 tests from IsOdd/IsOddTestFalseReturn (0 ms total)

[----------] Global test environment tear-down
[==========] 11 tests from 2 test cases ran. (0 ms total)
[  PASSED  ] 11 tests.

分析:

  从输出结果上,我们看到GTest框架将我们相同测试用例名的场景合并在一起,不同测试特例名的场景分开展现。
  
  虽然上例中,所有的执行都是正确的,但是如果以上测试中发生一个错误,也不能影响其他测试——不同测试用例不相互影响、相同测试用例不同测试特例不相互影响。我们称之为独立性。除了独立性,也不失灵活性——一个测试用例中可以通过不同宏(ASSERT_*类宏会影响之后执行,EXPECT_*类宏不会)控制是否影响之后的执行。
  

3. 预处理

  上述的测试用例是获取单个参数来进行测试,在实际中,我们的函数中往往需要多个参数,在每次测试时都构造一次测试用例,这比较麻烦,因此gtest为我们提供了一种提前构建数据的方式:
  

 int Add(int x,int y)                                                                                                             
 {                                                                                                                                
    return x+y;                                                                                                                    
  }                                                                                                                                

  struct Param{                                                                                                                    
    int _x;                                                                                                                        
    int _y;                                                                                                                        
   int _sum;                                                                                                                      
    Param(int x = 0,int y = 0, int sum = 0)                                                                                        
      :_x(x)                                                                                                                       
      ,_y(y)                                                                                                                       
      ,_sum(sum)                                                                                                                   
    {}                                                                                                                             

  };     
  class AddTest : public testing::TestWithParam<Param>                                                                             
  {                                                                                                                                
    public:                                                                                                                        
      virtual void SetUp(){                                                        
       Param p = GetParam();                                                                                                      
        std::cout << "case.x:"<< p._x << "case.y" << p._y <<"case.sum:"<< p._sum << std::endl;                                     
      }                                                                                                                            
      virtual void TearDown(){                                                                                                     

      }                                                                                                                            

      Param p;   
  };                                                                                                                               

 TEST_P(AddTest,test){//真正测试部分,这里将参数传递过去                                                                                             
   EXPECT_EQ(Add(p._x,p._y),p._sum);                                                                                              
 }                                                                                                                                
                                                                                                                                                                                                                                                         INSTANTIATE_TEST_CASE_P(AddTest,AddTest,testing::Values(Param(1, 1, 2),Param(2, 4, 6),Param(3,4,7)));    

TEST_P(AddTest,test1){//真正测试部分,这里将参数传递过去                                                                                             
   EXPECT_EQ(Add(p._x,p._y),p._sum);                                                                                              
 }                         

分析:
  我们让AddTest继承了testing::TestWithParam< T >(注:testing::TestWithParam< T >继承了testing::Test)并且重载了SetUp方法,这样我们每次执行AddTest的一个测试特例时,SetUp方法都会执行一次,从而将数据准备完毕。这样我们只要在一个类中构建好数据就行了。这儿需要注意一下TEST_P宏,它的第一参数要求是类名——即AddTest——不像TEST宏的第一个参数我们可以随便命名。
注:INSTANTIATE_TEST_CASE_P 这个宏只能为一个测试用例提供参数

猜你喜欢

转载自blog.csdn.net/zhangye3017/article/details/81112049