1、前言
对于一个成熟的系统,为了保证系统正确的运行,测试代码量与功能代码量应该是相当的。对于C++而言,目前已经有一些单元测试框架,如gtest。本文对gtest的使用做一个简单的介绍。
2、第一个测试用例
作为使用gtest的第一个用例,我们用以下示例来示范gtest的使用方法:
#include "gtest/gtest.h"
bool isEven(int n)
{
return !(n & 1);
}
TEST(HelloGtest, FirstTest)
{
ASSERT_TRUE(isEven(2));
EXPECT_TRUE(isEven(2));
ASSERT_FALSE(isEven(1));
EXPECT_TRUE(isEven(3));
}
int main(int argc, char *argv[])
{
testing::InitGoogleTest(&argc, argv);
RUN_ALL_TESTS();
}
以上的函数isEven是用于判断传入的参数是否为偶数,是则返回true,否则返回false。
TEST(HelloGtest, FirsTest)是一个测试用例,用于测试isEven函数,对于TEST宏,gtest的定义是TEST(test_case_name, test_name),所以这里的“HelloGtest”即为测试用例名称,而“FirstTest"为测试名称。事实上,应该理解为[Test_suit_name, Test_case_name],在后面我们解释原因。
在这个测试用例中,我们看到我们使用了三个宏:
ASSERT_TRUE,
ASSERT_FALSE,
EXPECT_TRUE,这些宏称之为断言,它们用于判断传入的参数是否为期望值
。在gtest中有两类断言:ASSERT_*和EXPECT_*,这二者的区别是:
1.当ASSERT_*断言失败时,后续的测试代码不会执行,当前测试案例会立即返回;
2.当EXPECT_*断言失败时,后续测试代码会继续执行,在最后报一个fail;
main函数中,我们看到首先执行testing::InitGoogleTest(&argc, argv),这句用于初始化gtest环境,它接收命令行参数,在gtest中有非常多的参数,这些参数可以控制gtest输出行为等,在后续文章中我会详细的介绍这些参数。然后是调用RUN_ALL_TESTS(),调用这个宏时,gtest会自动运行所有的测试用例。事实上,gtest存在一个测试用例管理列表,上述TEST负责将"HelloGtest"这个测试用例注册到测试用例列表中,然后RUN_ALL_TESTS()宏负责遍历测试用例列表,并逐个运行。
程序的运行结果如下:
以上为gtest的默认输出模式,绿色表示通过,红色表示失败。在失败时,会显示具体的失败于原因。在最后,会给出总结信息,即通过测试用例的个数以及有哪些测试用例失败了。如果我们需要更多的失败信息,我们可以利用"<<"操作符来提供额外的信息,如:
EXPECT_TRUE(isEven(3)) << "3 is not even";
这样一来运行,当这个失败时,这条错误信息就会显示出来:
另外,前面提到过TEST宏的两个参数应该理解为[Test_suit_name, Test_case_name],从运行的输出结果的第4行“[ RUN ] HelloGtest.FirstTest"这行我们可以知道,这里的“HelloGtest”为一个测试套件的名称,它可以包含多个测试用例,这里只有“FirstTest"这一个测试用例。而我们也可以在这个测试套件中增加更多的测试用例,如增加以下测试用例:
TEST(HelloGtest, SecondTest)
{
ASSERT_FALSE(isEven(5));
EXPECT_FALSE(isEven(7));
}
那么运行结果如下所示, “HelloGtest”这个测试套件里就有“FirstTest”和“SecondeTest”两个测试用例:
3、总结
本文只讲了gtest最基本的应用,在后续文章我会更加深入的介绍gtest的使用。