代码改变世界

Google C++单元测试框架(Gtest)系列教程之六——FAQ节选

2011-10-25 23:19  bangerlee  阅读(6981)  评论(0编辑  收藏  举报

这一节,我们来看Gtest的FAQ(Frequently-Asked Questions)。


为什么测试用例和测试实例命名中不应包含下划线

在C++中,对于以下情况,相应的标识可能会被编译器或标准库使用:

  1. 以下划线开始并紧接一个大写字母的标识
  2. 包含连续两个下划线的标识

为避免标识符冲突,用户代码中不应自定义以上两种情况的标识。使用TEST()或TEST_F()时,滥用下划线,将有可能产生标志符命名冲突。

当我们定义以下测试实例并执行测试程序时,Gtest会为我们生成一个名为TestCaseName_TestName_Test的类。

TEST(TestCaseName, TestName)

如果TestCaseName或TestName中包含下划线,情况会怎样呢?

  • TestCaseName以"_"开头(例如_Foo),我们得到_Foo_TestName_Test
  • TestCaseName以"_"结尾(例如Foo_),我们得到Foo__TestName_Test
  • TestName以"_"开头(例如_bar),我们得到TestCaseName__bar_Test
  • TestName以"_"结尾(例如bar_),我们得到TestCaseName_bar__Test

以上命名方式都有可能产生命名冲突,因而TestCaseName和TestName以“_"开头或结尾均不可取。

如果TestCaseName或TestName命名中包含下划线,情况又会怎样呢?

TEST(Time, Flies_Like_An_Arrow) { ... }
TEST(Time_Flies, Like_An_Arrow) { ... }

假设我们同时定义了两个测试实例,Oops! 这时Gtest将产生同一个类:Time_Flies_Like_An_Arrow。

因而为避免命名冲突的情况发生(不管是与系统标志冲突或自定义的标志间冲突),我们的测试用例或测试实例的命名最好不包含下划线。当然,这是建议而不是必须的。

在测试固件类中,为什么要用set-up/tear-down函数,而不使用构造函数/析构函数

还记得测试固件的作用吗?通过测试固件,Gtest为每一个测试实例生成一个测试固件对象,该对象为每个测试实例提供独立的数据配置,通过编写SetUp()/TearDown()函数,我们可以对数据进行初始化和销毁操作。

对于一个类而言,构造函数和析构函数不是同样有初始化数据/销毁数据的作用吗?Gtest提供SetUp()和TearDown()岂不是多此一举?No,no,no, 对于以下情况,还非得用SetUp()/TearDown()不可:

对于销毁操作中包含异常抛出调用的,由于在C++的析构函数中不能抛出异常,这时候需使用TearDown()调用(关于C++析构函数抛出异常的介绍,请看这里)。

为什么当我调用RUN_ALL_TESTS()函数时,编译器抛出"ignoring return value"警告

一些Gtest使用者忽略了RUN_ALL_TESTS()的返回值,理应这样调用:

return RUN_ALL_TESTS();

而不是这样:

RUN_ALL_TESTS();

测试程序根据RUN_ALL_TESTS()的返回值判断其所包含的测试实例是否通过。如果在main()函数中忽略其返回值,即使是某个测试实例检测失败,整个测试程序也会被认为是无检测失败地成功执行。

为避免误用RUN_ALL_TESTS(),对于不作为main()返回值的调用,gcc将对此抛出警告,为消除该警告,将RUN_ALL_TESTS()作为main()函数的返回值即可。

如何为一个测试固件定义多个测试用例

我想编写多个测试实例,它们对应于同一个测试固件,对此,是否要为每一个测试实例编写新的测试固件类?就像这样:

class FooTest : public BaseTest {};

TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }

class BarTest : public BaseTest {};

TEST_F(BarTest, Abc) { ... }
TEST_F(BarTest, Def) { ... }

这里类FooTest和类BarTest什么都不做,我们这样定义只是为了产生两个不同的测试用例名。

其实使用typedef能更便捷地达到目的:

typedef BaseTest FooTest;

TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }

typedef BaseTest BarTest;

TEST_F(BarTest, Abc) { ... }
TEST_F(BarTest, Def) { ... }


关于Gtest的更多FAQ,请参看这里