这一节,我们来看Gtest的FAQ(Frequently-Asked Questions)。
为什么测试用例和测试实例命名中不应包含下划线
在C++中,对于以下情况,相应的标识可能会被编译器或标准库使用:
- 以下划线开始并紧接一个大写字母的标识
- 包含连续两个下划线的标识
为避免标识符冲突,用户代码中不应自定义以上两种情况的标识。使用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,请参看这里。