Google C++单元测试框架(Gtest)系列教程之五——再论测试固件

引言

《Google C++单元测试框架(Gtest)系列教程之三——测试固件(Test fixture)》中,介绍了如何使用测试固件为测试实例(Tests)进行数据配置和初始化。除了数据初始化方法,Gtest还提供了测试实例间共享数据的方法。

同属一个测试用例的测试实例间共享数据

为实现测试实例间的独立性,Gtest提供了为每个测试实例新生成一个测试固件对象的方法,通过“独享”测试对象中的数据,保证了一个测试实例的执行不会对其他实例的执行产生影响。但是,对于以下情况:

  1. 初始化数据涉及内存申请等操作,为每个测试实例构造对象将带来较大系统开销;
  2. 存在某数据,其在每个实例中均被用到,但每个实例都不会更改该数据的值;

我们就没有必要将这些数据放入测试固件对象中了,在一个C++类中,使用什么方法能让数据独立于对象之外、又能被对象访问呢?


没错!就是使用C++类的static成员变量,具体定义方法如下:

  1. 在测试固件类中,将需要在测试实例间共享的数据声明为static类型;
  2. 定义函数SetUpTestCase(),用于初始化共享数据;定义函数TearDownTestCase(),用于清理共享数据。这两个函数的函数类型均为static void。

在测试程序执行时,Gtest在第一个测试实例运行之前调用SetUpTestCase(),在最后一个测试实例运行之后调用TearDownTestCase(),在此期间,测试实例可以使用所定义的共享数据。

我们来看一个在测试实例间共享数据的实例:

class FooTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
shared_resource_ = new ...;
}
static void TearDownTestCase() {
delete shared_resource_;
shared_resource_ = NULL;
}
// You can define per-test set-up and tear-down logic as usual.
virtual void SetUp() { ... }
virtual void TearDown() { ... }

// Some expensive resource shared by all tests.
static T* shared_resource_;
};

T* FooTest::shared_resource_ = NULL;

TEST_F(FooTest, Test1) {
... you can refer to shared_resource here ...
}
TEST_F(FooTest, Test2) {
... you can refer to shared_resource here ...
}

由于Gtest不一定按照我们声明的顺序执行测试实例,因此我们的测试实例仍需保持独立,避免滥用共享数据造成的测试实例相互依赖的情况。在测试实例中,要不不改变共享数据的值,要不在改变数据值之后、执行完之前还原共享数据的值。

程序级别数据共享

正如前面介绍的,Gtest提供了测试实例(Tests)和测试用例(Test Case)级别的数据管理的方法,除此之外,Gtest在程序级别提供了共享数据管理方法,使得我们可以在测试用例和测试实例间共享数据。

为实现在程序级别共享数据,首先我们需要定义一个继承自::testing::Environment的类,并且编写SetUp()和TearDown()函数覆盖父类中的相应虚函数,该类中的成员变量即可作为共享数据:

class Environment {
public:
virtual ~Environment() {}
// Override this to define how to set up the environment.
virtual void SetUp() {}
// Override this to define how to tear down the environment.
virtual void TearDown() {}
};

其次,调用以下接口“注册”类对象:

Environment* AddGlobalTestEnvironment(Environment* env);

其参数为“注册”前的类对象指针,返回值为“注册”后的类对象指针。下面我们来看实例:

class FooEnvironment: public testing::Environment
{
public:
virtual void SetUp()
{
printf("Environment SetUp!\n");
a = 100;
}
virtual void TearDown()
{
printf("Environment TearDown!\n");
}
int a;     //共享数据
};
FooEnvironment* foo_env;  //对象指针声明
TEST(firstTest, first)    //访问共享数据并改变它的值
{
printf("in the firstTest, foo_env->p is %d\n", foo_env->a);
foo_env->a ++;
}
TEST(secondTest, second)  //访问共享数据
{
printf("in the secondTest, foo_env->p is %d\n", foo_env->a);
}
int main(int argc, char* argv[])
{
foo_env = new FooEnvironment;
testing::AddGlobalTestEnvironment(foo_env);     //注册
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

上面的测试用例firstTest和secondTest均访问了共享数据,作为演示,firstTest修改了共享数据的值。该测试程序执行结果如下:

[==========] Running 2 tests from 2 test cases.
[----------] Global test environment set-up.
Environment SetUp!
[----------] 1 test from firstTest
[ RUN ] firstTest.first
in the firstTest, foo_env->p is 100
[ OK ] firstTest.first (0 ms)
[----------] 1 test from firstTest (0 ms total)

[----------] 1 test from secondTest
[ RUN ] secondTest.second
in the secondTest, foo_env->p is 101
[ OK ] secondTest.second (0 ms)
[----------] 1 test from secondTest (0 ms total)

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


小结

在Gtest中,测试实例间共享数据的方式有两种(除全局变量的方式外),一种是让同属一个测试用例的测试实例间共享数据,另一种是可让程序中的所有测试实例共享数据。测试实例间进行数据共享,破坏了测试实例间执行的独立性,个人认为应该尽量避免使用。


Reference: googletest project


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值