近做了一系列的单元测试相关的工作,除了各种规范及测试框架以外,讨论比较多的是关于代码覆盖率的产生,c/c++与其他的一些高级语言或者脚本语言相比较而言,例如 Java、.Net和php/python/perl/shell等,由于没有这些高级语言和脚本语言的反射的特性,其代码覆盖率的产生过程会稍微复杂一些。发现许多同学对C++的覆盖率如何产生在都不太清楚,这里做一个简单的介绍。

  一、基本使用方法

  在Linux上的c/c++开发一般都使用gcc/g++作为主要的编译器,如果需要产生覆盖率数据需要在Makefile或者Scons文件中做下面的编译链接设置,

  编译的时候,增加 -fprofile-arcs -ftest-coverage 或者 –coverage;

  链接的时候,增加 -fprofile-arcs 或者 –lgcov;

  打开–g3 选项,去掉-O2以上级别的代码优化选项;否则编译器会对代码做一些优化,例如行合并,从而影响行覆盖率结果;

  基本要求上面三点,但有一个建议,为了上述几个编译选项的使用不影响到正常的编译过程(否则会极大地影响程序的运行效率)。在使用makefile中通过参数传递来支持覆盖率产生,可以在makefile使用下面的方式,

  ifeq ($(coverage), yes)

  CXXFLAGS += -fprofile-arcs -ftest-coverage

  LINKERCXX += -fprofile-arcs -ftest-coverage

  OPT_FLAGS = -g3

  endif

  这样,可以使用 make coverage=yes 来引入这些编译选项而不会影响到正常的编译(scons同理)。

  二、简单示例

  这里写了一个简单的程序做测试,主要包含三个文件:Rectangle.cpp, RectangleTest.cpp, Makefile。

  1)Rectangle.cpp 是被测代码,里面定义了一个简单的类Rectangle(长方形),里面有三个方法:

  set_values(),设置长方形对象的长和宽;

  area(),求长方形的面积;

  lenth(),求长放形的周长;

  2)RectangleTest.cpp 是一个简单的测试程序,为了demo使用,并没有使用cppunit/gtest这样的单元测试框架,直接使用了main()函数来调用Rectangle里面的方法;

  Rectangle.cpp和RectangleTest.cpp的代码如下图,