sample5演示如何使用一个test fixture衍生出多个test fixture以在多个test中使用。
由于在使用某个test fixture时,test case的名字必须是test fixture的名字,是一一对应的关系。所以在使用一个test fixture只能被一个test case使用。
但是有时多个test case中希望使用相同的test fixture,或者功能略有不同的test fixture。例如,可能想确保对所有GUI库的测试不泄漏重要的系统资源,如测试“字体”和“笔刷”两个东西。在Google Test中可以把相同的逻辑丢到一个父test fixture中,而后让需要用到这个功能的test fixture继承自该test fixture。
sample5_unittest中的测试对象使用了sample1和sample3中的内容,因此sample5的CMake编译规则如下,接着在test/src/samples/CMakeLists.txt
最后添加如下两行(sample3没有.c源文件)。
add_executable(sample5_unittest sample1.cc sample5_unittest.cc)
target_link_libraries(sample5_unittest PUBLIC gtest gtest_main)
sample5_unittest中的内容
sample5_unittest.cc中定义了三个test fixture,以及使用他们的test。首先是父test fixture的内容。
class QuickTest: public testing::Test {
protected:
void SetUp() override { start_time_ = time(nullptr); }
void TearDown() override {
const time_t end_time = time(nullptr);
EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
}
time_t start_time_;
};
QuickTest
用来判断整个Test的运行时间是否超过5s。整体实现方式是利用了方法SetUp
和TearDown
的调用时机。即在test开始时记录下test的开始时间戳,而后在test结束的时候判断结束时间戳和开始时间戳的差值。
这样所有的继承自QueckTest
的test fixture都会自动增加test运行时常是否超过5S的判断条件。
而后定义了另一个test fixtureIntegerFunctionTest
其直接继承自QueckTest
,内部没有定义任何特殊的操作。
class IntegerFunctionTest: public QuickTest {};
接着是使用IntegerFunctionTest
test fixture。
TEST_F(IntegerFunctionTest, Factorial) {
EXPECT_EQ(1, Factorial(-5));
EXPECT_EQ(1, Factorial(-1));
EXPECT_GT(Factorial(-10), 0);
EXPECT_EQ(1, Factorial(0));
EXPECT_EQ(1, Factorial(1));
EXPECT_EQ(2, Factorial(2));
EXPECT_EQ(6, Factorial(3));
EXPECT_EQ(40320, Factorial(8));
}
TEST_F(IntegerFunctionTest, IsPrime) {
EXPECT_FALSE(IsPrime(-1));
EXPECT_FALSE(IsPrime(-2));
EXPECT_FALSE(IsPrime(INT_MIN));
EXPECT_FALSE(IsPrime(0));
EXPECT_FALSE(IsPrime(1));
EXPECT_TRUE(IsPrime(2));
EXPECT_TRUE(IsPrime(3));
EXPECT_FALSE(IsPrime(4));
EXPECT_TRUE(IsPrime(5));
EXPECT_FALSE(IsPrime(6));
EXPECT_TRUE(IsPrime(23));
}
至于test中使用的语句则没有新的东西,在sample1中已经看过。
最后是另一个test fixture QueueTest
的定义:
class QueueTest : public QuickTest {
protected:
void SetUp() override {
QuickTest::SetUp();
q1_.Enqueue(1);
q2_.Enqueue(2);
q2_.Enqueue(3);
}
Queue<int> q0_;
Queue<int> q1_;
Queue<int> q2_;
};
和上一个test fixtureIntegerFunctionTest
不同的是这个test fixture需要使用SetUp
方法初始化一些被测试对象,因此在自己的SetUp
中需要手动调用父类的SetUp
方法。TearDown
方法也是如此(当然由于这个test fixture不必使用TearDown
方法析构一些东西,因此可以直接忽略对其的定义)。
在最后则是两个使用QueueTest
的两个test,没有什么新的东西,不再chao了。
总结一下:虽然test fixture在使用时必须和test case同名,但是可以利用继承方式来实现对test fixture的复用。将公用的功能丢到一个test fixture中,而后让需要使用公用功能的test fuxture继承子它即可,这样便可以在不同的test case中复用相同功能。