引言
本文将先介绍单元测试的相关概念,然后引入Google的开源C++单元测试框架Gtest,最后通过编译、运行Gtest自带的一个测试样例,介绍如何在Unix/Linux下使用Gtest。
单元测试
说到单元测试,大家应该不会陌生。作为软件开发过程中最低级别的测试环节,单元测试一般由编码人员自己完成,它的目的是隔离程序部件,并证明这些单个部件满足预期的功能。在静态程序分析、代码检视之后进行单元测试,可以帮助我们在开发过程的早期发现问题。好的测试具备以下特点:
1.独立。一个测试用例应该是独立的,所谓“独立”,即该测试用例的测试结果不受其他测试的影响,下面的例子简单地说明了单元测试的独立性:
1 #include <assert.h>
2 int glob[3] = {1, 2, 3};
3 int* g_p = glob;
4 int alloc(void)
5 {
6 return *g_p++;
7 }
8 int release(void)
9 {
10 return *g_p--;
11 }
12 void test_1(void)
13 {
14 assert(1 == alloc());
15 //release();
16 }
17 void test_2(void)
18 {
19 assert(1 == alloc());
20 //release();
21 }
22 int main()
23 {
24 test_1();
25 test_2();
26 return 0;
27 }
在上面的例子中,test_2的断言会被抛出,显然它的运行受到了test_1的影响,test_1中进行了申请(alloc),理应进行释放(release),以保证该用例在运行前后程序的状态一致。
2.有效的组织架构,清晰的命名。各个测试用例针对不同的测试对象,而对单个测试对象而言,又可能有多个测试用例对应该对象的多个功能。好的习惯是把这些用例以层次结构的形式组织起来,并使用清晰的命名,使得我们通过阅读用例名称即可明了该用例的功能。
3.可移植、可复用。像我们对程序平台性无关的苛刻要求一样,对于优秀的测试,我们也期望做到在不同的操作系统、编译器间进行方便地移植。
4.当用例失败时,提供尽可能多的有效信息。毋庸置疑,提示信息越是清晰和全面,越方便我们定位问题、高效地找出程序中的bug。
如今有不少测试框架帮助我们完成单元测试,像针对C++的有Google Test、CppUnit,针对C的有CUnit,针对Java的有JUnit,这些测试框架为我们实现独立、可移植、可复用、有组织的测试提供了条件,使我们能够专注于编写程序功能相关的测试代码。下面介绍Gtest的使用方法。
Google C++单元测试框架
Google C++单元测试框架(简称Gtest),可在多个平台上使用(包括Linux, Mac OS X, Windows, Cygwin和Symbian),它提供了丰富的断言、致命和非致命失败判断,能进行值参数化测试、类型参数化测试、“死亡测试”。Gtest是一个开源的项目,其源码可以从这里下载,目前的代码发行版是1.6.0。
编译
源码包中的README文件说明了如何编译Gtest源码,目录msvc、xcode中分别包含了Windows、Mac OS X平台相关的项目文件,cmake目录下是使用CMake进行Makefiles和项目生成的相关文件,如果你在Unix/Linux下,直接在源码目录下执行make命令即可编译。
如果执行make的过程中遇到如下出错提示:
./src/gtest-death-test.cc:970:73: error: ‘clone’ was not declared in this scope
make: *** [src/gtest-all.lo] Error 1
在/src/gtest-death-test.cc文件中,将第970行的代码:
970 child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
改成:
970 child_pid = fork();
使用make编译过后并不需要执行make install命令安装Gtest相关的头文件和库文件,对自己的测试代码进行编译时,从当前目录引用头文件和库文件即可。
执行用例
源码文件的samples目录下为我们提供了多个用例,从sample1到sample9,Gtest作者由浅入深为我们讲解了Gtest的用法,怎么执行这些用例呢?
首先进入源码目录下的make目录,其中包含了一个Makefile文件,执行make命令,make命令执行过后可以看到该目录下增加了几个文件,其中sample1_unittest就是sample1的可执行文件了。执行./sample1_unittest即可看到测试的运行结果:
为编译生成其他用例的可执行文件,我们可以参照make目录下的Makefile文件,或者执行以下步骤:
将gtest-main.a动态库文件拷贝到samples目录下,执行以下命令:
$ g++ -I ../include/ -c sample2_unittest.cc
以及:
$ g++ -I ../include/ sample2.o sample2_unittest.o gtest_main.a -lpthread -o test2
最后我们得到了sample2的可执行文件test2,经过这几步,相信大家也懂得了如何生成自己的Gtest测试执行文件。
小结
本文介绍了良好的测试代码所具备的一些特点,对Gtest作了简要介绍,说明了如何编译Gtest测试代码、生成Gtest测试可执行文件。接下来的文章将详细介绍Gtest的使用方法,包括断言、函数测试、测试固件、参数化、“死亡测试”等内容。
Reference: googletest project