GTest源码剖析(三)——TEST_F宏

本文深入剖析了GTest中的TEST_F宏与TEST宏的区别,详细介绍了TEST_F宏的定义及其实现原理,并通过实例对比了两种宏在拼接类及调用MakeAndRegisterTestInfo()传参方面的差异。

GTest源码剖析——TEST_F宏

1 TEST_F宏与TEST宏的区别

TEST_F宏和TEST宏的实现非常接近,只是TEST_F宏的封装更加开放一些,所以对TEST宏的功能多了一些扩展。
详细见GTest源码剖析——TEST宏

1.1 TEST_F宏定义

#define TEST_F(test_fixture, test_name)
  GTEST_TEST_(test_fixture, test_name, test_fixture, 
              ::testing::internal::GetTypeId<test_fixture>())

1.2 TEST宏定义

//step1
#if !GTEST_DONT_DEFINE_TEST
# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
#endif

//step2
#define GTEST_TEST(test_case_name, test_name)
  GTEST_TEST_(test_case_name, test_name,::testing::Test, ::testing::internal::GetTestTypeId())

1.3 对比分析

eg:

TEST(Call,makeCall);
TEST_F(Call,makeCall);
1.3.1 拼接类对比

区别在于:
TEST宏中的拼接类Call_makeCall_Test继承于Test类;
TEST_F宏中的拼接类Call_makeCall_Test继承于Call类;

即相对于TEST宏,TEST_F可以覆盖Test类中的虚函数SetUp()和TearDown()。

TEST宏:

class Call_makeCall_Test : public ::testing::Test    
{    
public:    
    Call_makeCall_Test();    

private:    
    virtual void TestBody();
    static ::testing::TestInfo* const test_info_ ; 

    Call_makeCall_Test(Call_makeCall_Test const &);
    void operator=(Call_makeCall_Test const &);
};  

TEST_F宏:

class Call_makeCall_Test : public ::testing::Call    
{    
public:    
    Call_makeCall_Test();    

private:    
    virtual void TestBody();
    static ::testing::TestInfo* const test_info_ ; 

    Call_makeCall_Test(Call_makeCall_Test const &);
    void operator=(Call_makeCall_Test const &);
};  
1.3.2 调用MakeAndRegisterTestInfo()传参对比

区别在于:
TEST宏: 传入MakeAndRegisterTestInfo()的参数为::testing::Test::SetUpTestCase和::testing::Test::TearDownTestCase。
TEST_F宏: 传入MakeAndRegisterTestInfo()的参数为Call::SetUpTestCase和Call::TearDownTestCase。

即相对于TEST宏,TEST_F可以定义自己的SetUpTestCase和TearDownTestCase。

TEST宏:

::testing::TestInfo* const Call_makeCall_Test::test_info_ =   
    ::testing::internal::MakeAndRegisterTestInfo(  
        "Call",   
        "makeCall",   
        NULL,   
        NULL,   
        ::testing::internal::CodeLocation(__FILE__, __LINE__), 
        ::testing::internal::GetTestTypeId(),
        ::testing::Test::SetUpTestCase,   
        ::testing::Test::TearDownTestCase,   
        new ::testing::internal::TestFactoryImpl<Call_makeCall_Test>);   

TEST_F宏:

::testing::TestInfo* const Call_makeCall_Test::test_info_ =   
    ::testing::internal::MakeAndRegisterTestInfo(  
        "Call",   
        "makeCall",   
        NULL,   
        NULL,   
        ::testing::internal::CodeLocation(__FILE__, __LINE__), 
        ::testing::internal::GetTestTypeId(),
        Call::SetUpTestCase,   
        Call::TearDownTestCase,   
        new ::testing::internal::TestFactoryImpl<Call_makeCall_Test>);   

2 TEST_F宏作用:

2.1 TestCase级扩展

  1. SetUpTestCase()方法在TestCase的第一个test之前执行.
  2. TearDownTestCase()方法在TestCase的最后一个test之后执行.
  3. 在TestCase为Call的测试用例中,可以共享_callServer,可以跨越多个test。
class Call : public testing::Test 
{
protected:
  static void SetUpTestCase() 
  {
    CallServer *_callServer = new CallServer;
  }

  static void TearDownTestCase() 
  {
    delete _callServer;
    _callServer = NULL;
  }

  static CallServer* _callServer;
};

2.2 Test级扩展

  1. SetUp()方法在每个Test之前执行
  2. TearDown()方法在每个Test之后执行
  3. 在TestCase为Call的测试用例中,可以共享_callInfo,SetUp会在下一个test重新调用,所以逐个对每一个test生效。
class Call : public testing::Test 
{
protected:
    virtual void SetUp()
    {
        CallInfo *_callInfo = new CallInfo;
    }
    virtual void TearDown()
    {
        delete _callInfo;
        _callInfo = NULL;
    }

    CallInfo* _callInfo;
};

3 参考

github: googletest


ZhaiPillar
2017-09-16

### TEST_F 的用法与定义 `TEST_F` 是 Google Test 框架中的一个重要,用于定义基于测试夹具(fixture)的单元测试案例。它允许开发者通过共享相同的上下文来运行多个相关的测试案例。以下是关于 `TEST_F` 的详细介绍: #### 1. 基本概念 `TEST_F` 通常与 `TEST_FIXTURE` 或者自定义的测试类一起使用。这种模式的核心在于创建一个派生自 `testing::Test` 的测试夹具类,在该类中可以初始化一些通用资源或者状态变量[^3]。 #### 2. 使用方法 要使用 `TEST_F`,需要先定义一个继承自 `testing::Test` 的测试夹具类,并在其中提供必要的设置和清理逻辑。具体来说: - 测试夹具类可以通过重写 `SetUp()` 和 `TearDown()` 方法分别执行每项测试前后的准备工作以及收尾工作。 - 接着利用 `TEST_F` 来编写具体的测试函数。 下面是一个简单的例子展示如何应用这些组件: ```cpp #include <gtest/gtest.h> class MyFixture : public ::testing::Test { protected: void SetUp() override { // 在每个测试之前调用 value = 42; } void TearDown() override { // 在每个测试之后调用 value = 0; } int value; }; // 使用 TEST_F 创建第一个测试 TEST_F(MyFixture, FirstTest) { EXPECT_EQ(value, 42); } // 使用 TEST_F 创建第二个测试 TEST_F(MyFixture, SecondTest) { ++value; EXPECT_EQ(value, 43); } ``` 在这个实例里,我们首先声明了一个名为 `MyFixture` 的测试夹具类,这个类包含了成员变量 `value` 并且实现了 `SetUp` 函数用来初始化 `value` 到特定数值。接着,两个独立的测试被定义出来——它们都依赖于同一个初始条件即 `value=42` 这一点由 `TEST_F` 实现[^4]。 #### 3. 关键特性 - **重复使用的环境**: 当有若干个测试都需要相同的数据结构或对象时,就可以把这些共有的部分放在测试夹具里面。 - **自动化的生命周期管理**: 自动调用 `SetUp` 和 `TearDown` 方法确保每次单独测试都能在一个干净的状态下开始并结束。 #### 4. 注意事项 虽然 `TEST_F` 提供了一种方便的方式来组织具有共同需求的测试集,但也需要注意不要让测试之间相互影响;每一个测试应该保持其独立性和可预测的结果[^5]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值