使用CUnit进行单元测试的一些窍门

其实用CUnit进行单元测试很容易,因为C语言本身提供了宏替换这个强大的工具,可以很容易的实现非侵入式的测试。这里我们只讨论linux下使用gcc进行单元测试的情况,msvc不在讨论范围。

 

1.测试static的函数,static的语义是只有同一单元的代码才能访问static的函数或者变量,为了绕过这个限制,我们的测试 程序,需要直接

include待测试的CPP文件

 

#include "test.cpp"

 

2.比如C++类中有很多成员或者是private隔离级别的,测试时为了确认测试结果,很多时候需要调用这些函数,我们可以利用宏定义来绕过这些限制

#define protected public
#define private public

#include "test.cpp"

3. 比如有时我们想让标准函数fgets失败,来测异常情况,但是真正的失败有时很难做出来,那么我们就需要利用宏定义来替换指定的函数

#include <stdio.h>

static bool errflag = false;
static char *myfgets(char *s,int size,FILE *stream)
{
    if(errflag)
    {
        return fgets(s,size,stream);
    }
    else
    {
        return NULL;
    }
}

#undef fgets
#define fgets myfgets

#include "test.cpp"

用上面的方法我们就把标准库函数给替换了

 4. 确认代码覆盖率和分支覆盖率

作为白盒测试的单元测试,我们的最低目标是代码100%,如果可能的话分支覆盖率也要达到100%, 我们在编译单元测试程序时,需要添加下面的编译选项

AM_CXXFLAGS=-O0 -fprofile-arcs -ftest-coverage
 

O0禁用所有优化,-fprofile-arcs -ftest-coverage用来编译代码覆盖率信息。

编译后,会在当前目录下生成*.gcno 文件,运行我们的测试程序后,会在当前目录下生成*.gcda文件,运行 gcov *.cpp就会生成很多的gcov文件,所有没有被覆盖的代码行会显示#####,我们只要搜索#####就可以知道那些代码还没测到。

要想知道分支覆盖率的话,只要执行gcov -b *.cpp命令就行,这时生成的gcov文件中会多出分支覆盖情况,我们只要搜索taken 0%的,一般就是没有被覆盖的分支。分支100%覆盖率是很难达到的,

if ( a || b)

   xxxx

代码覆盖只要满足a 就可以,但是分支覆盖 需要 a, b, not a and not b 三个条件才行。

 

5.确认代码内存泄漏

除了分支覆盖率外,我们还需要保证代码没有内存泄漏,在linux提供了valgrind工具,可以用来检查内存,执行下面命令就可以了

valgrind --tool=memcheck --leak-check=full --leak-resolution=high --track-fds=yes ./test