单元测试是一种保证代码质量的手段。程序员可以通过写单元测试来保证自己写的代码的功能正确。

本人所在公司使用GoogleTest测试框架来进行单元测试。虽然现在在公司的工程代码中写单元测试已经驾轻就熟,但是只是知其然不知其所以然,所以再此对Google Test测试框架进行一个全面的了解与学习。

本文只涉及Google Test的使用,不涉及对其源码的学习与解读。

Linux环境搭建Google Test测试环境

Google Test托管在github上,先通过git把Google Test拉取到本地

git clone https://github.com/google/googletest.git

Google Test 提供了多平台的构建方式,在Linux上推荐使用cmake来编译

cd googletest
cmake .

编译完成之后生成静态库,以后编译自己的单元测试需要链接这些静态库

最后,安装,将头文件和编好的库文件放在系统指定目录下,此步骤需要root权限

make install

安装完成之后,可以尝试编译运行Google Test自带的sample

cd googletest/googletest/make
make
./sample1_unittest

运行结果如图所示:

GoogleTest初探(0)-LMLPHP

想要从头开始学些如何使用Google Test,去研究一下googletest/googletest/samples下的所有测试用例和googletest/googletest/doc目录下的指导文档,把这些搞清楚了,也就初步掌握了Google Test了。

基本测试

 

//myGtest.cpp
#include <gtest/gtest.h> int add(int a, int b) //待测试函数
{
return a + b;
} TEST(TestAdd, normal)//单元测试
{
EXPECT_EQ(, add(, ));
EXPECT_EQ(, add(, ));
} int main(int argc, char **argv)//初始化GoogleTest并运行所有单元测试
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

编译:

g++ myGtest.cpp -lgtest -lpthread -o myGtest

注意不仅要链接libgtest.a还要链接libpthread.a

运行结果:

GoogleTest初探(0)-LMLPHP

可以看到测试结果,符合add函数的预期行为。

对于基本测试行为,必须包含以下的要素:

1. 测试文件必须包含头文件 gtest/gtest.h;

2. 单元测试函数使用宏 TEST,没有返回类型,有两个参数:第一个测试是测试用例名,第二个参数是本测试名;

3. 测试内容和逻辑需要你自己编写,GoogleTest提供了一系列的宏(类似于安断言)来判断你的代码是否符合预期结果;

4. 需要有一个main函数来初始化并执行所有测试,这个main函数的写法是固定的(由于其是固定的,也可以不写main函数,Google Test提供了一个写好的main 函数只要在链接时链接libgtest_main.a即可),RUN_ALL_TESTS()来执行所有的测试。返回值为0说明全部测试通过,1则说明有失败的测试。

Test Fixtures

有些地方也翻译作测试夹具,我感觉找不到对其合适的翻译。

就是将有相同的流程或使用相同数据的测试用例聚合起来,共享同一套流程或同一份数据,这套流程或数据会在每个测试用例运行之前和之后执行固定的操作。

待测试类:

//MyClass.hpp
class MyClass
{
public:
int add(int a, int b)
{
return a + b;
} int plus(int a, int b)
{
return a * b;
}
};

测试:

//myGtest.cpp
#include <gtest/gtest.h>
#include <iostream>
#include "MyClass.hpp" class TestMyClass : public testing::Test //test fixture类
{
protected:
void SetUp() override//每个测试运行前调用
{
std::cout<<"test start"<<std::endl;
}
void TearDown() override//每个测试运行后调用
{
std::cout<<"test done"<<std::endl;
}
MyClass mc;
}; TEST_F(TestMyClass, testAdd)//测试用例1
{
EXPECT_EQ(, mc.add(, ));
} TEST_F(TestMyClass, testPlus)//测试用例2
{
EXPECT_EQ(, mc.plus(, ));
} int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

运行结果:

GoogleTest初探(0)-LMLPHP

可以看到测试结果,符合MyClass类的类方法的预期。并且在测试开始和结束时打印出来我们想要的提示信息

当一个测试执行时会发生以下事件:

1. GTest构造TestMyClass对象(我们称之为t1)。

2. t1.SetUp()函数初始化t1。

3. t1的第一个测试testAdd执行。

4. 在测试执行完后调用t1.TearDown()清理现场。

5. t1被析构。

6. 以上步骤重复一遍,这一轮是执行测试testPlus

使用Test Fixtures可以讲一些流程重复或者数据重用的测试用例聚合起来,更方便编写和维护

对于Test Fixtures而言,具有一下几个要素:

1. 从::testing::Test集成一个类。根据我们希望访问子类的fixture成员的权限,限定为protected或public

2. 在类中,定义任何你想使用的对象

3. 如果需要,实现默认的构造函数或SetUp()函数来为每个测试准备数据

4. 如果需要,实现析构函数和TearDown函数来释放SetUp()函数分配的资源

5. 如果需要,请自定义测试需要共享的函数

6. 使用时,用TEST_F代替TEST(在使用TEST_F前必须先定义好Test Fixtures 类)

7. TEST_F无返回值,有两个参数,第一个是Test Fixtures 类名,第二个是测试名

相关链接:

https://github.com/google/googletest/blob/master/googletest/docs/primer.md

https://www.cnblogs.com/panda_lin/p/gtest_primer.html

04-16 11:07