Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1563838
  • 博文数量: 237
  • 博客积分: 5139
  • 博客等级: 大校
  • 技术积分: 2751
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-18 14:48
文章分类

全部博文(237)

文章存档

2016年(1)

2012年(4)

2011年(120)

2010年(36)

2009年(64)

2008年(12)

分类: LINUX

2009-01-18 21:29:56

为什么需要代码覆盖率分析?

在发布代码的时候,我们常常会对其进行一系列的测试来协调软件的性能和功能,使他们和预计的相同。但是检验通常都是相当的困难,即使程序相当的简单。开发者常常会借助一些测试工具(test suite)来模拟或者重建执行脚本。如果测试程序组是彻底的,那么程序的各个功能都将被测试到并且都可以证明是可以工作的。

但是怎样才算彻底呢?简单点说就是测试程序的每一条路径,验证每一个结果,执行每一条语句,证明没一句语句是没用的。gcov就是一个用来检验你的每一句语句是否都执行了的工具。

 

什么是代码覆盖率分析?

代码覆盖率分析就是找到定位没用的或者不执行的代码的过程。没用的代码不会存在什么问题,但是他们会影响程序的可读性;不执行的代码则可能是未来bug的所在。所以找到他们,把他们从你的程序中移处是大有裨益的。

覆盖率分析主要有下面的几个过程:

    通过测试程序组找到不执行的程序段;

    添加额外测试程序组,以便增加代码覆盖率;

    决定代码覆盖率的定量测度,它也是程序质量的间接测度。

 

代码覆盖率分析的缺陷

代码覆盖率分析不能找出程序的逻辑错误。考虑一下下面的代码

10:  rc = call_to_xx ();

11:  if (rc == ERROR_FATAL)

12:    exit(2);    /* exit with error code 2 */

13:  else

14:    /* continue on */

当测试程序段运行到11行时,11行始终都不能为真。call_to_xx返回了另外的一个错误比如ERROR_HANDLE,除非我们加入这种错误的处理方式的代码。

代码覆盖测试工具不会告诉你什么是必须的,他们只能显示已经存在的代码的覆盖率。

 

代码覆盖率的类型

gcov可以用来测量各种形式的代码覆盖率。最常见最有用的两种是分支覆盖(branch coverage)和循环覆盖(loop coverage

分支覆盖证明各个方向的每一条分支都被执行到了。循环覆盖试图证明循环内部的每一条路径都被测试到了。循环覆盖似乎非常的复杂,但基本上只要满足下面的三个状况,就可以作了。

    1。循环条件不满足,循环没有内部没有执行;

    2。循环条件就满足了一次,循环内部就执行了一次;

    3。循环条件至少满足了两次,循环至少执行了两次。

举个例子

void  function(int number)

{

  if (number % 2) == 0)

    printf("even \n");

  for (;number < 9; number++){

    printf("number is %d\n", number);

  }

}

function(11);   满足状况一

function(8);    满足状况二

function(6);    满足状况三   

 

代码覆盖率工具gcov的使用

要使用gcov,需要在我们用gcc编译程序时加入两个参数fprofile-arcsftest-coverage.

fprofile-arcs参数使gcc创建一个程序的流图,之后找到适合图的生成树。只有不在生成树中的弧被操纵(instrumented):gcc添加了代码来清点这些弧执行的次数。当这段弧是一个块的唯一出口或入口时,操纵工具代码(instrumentation code)将会添加到块中,否则创建一个基础块来包含操纵工具代码。

gcov主要使用.gcno.gcda两个文件

.gcno是由-ftest-coverage产生的,它包含了重建基本块图和相应的块的源码的行号的信息。

.gcda是由加了-fprofile-arcs编译参数的编译后的文件运行所产生的,它包含了弧跳变的次数和其他的概要信息。

下面是一个简要的范例:

  1 #include

  2 #include

  3

  4 int main(int argc,char** argv)

  5 {

  6     int x,y;

  7     int arraysize;

  8     int **array;

  9

 10     if(argc!=2)

 11     {

 12         printf("Usage: %s Enter arraysize value\n;",argv[0]);

 13         exit(-1);

 14     }

 15     else

 16     {

 17         arraysize = atoi(argv[1]);

 18         if(arraysize <=0)

 19         {

 20             printf("Array size must be larger than 0\n;");

 21             exit(-1);

 22         }

 23     }

 24

 25     array = (int**) malloc( arraysize*sizeof(int*));

 26

 27     printf("Creating an %d by %d array \n",arraysize,arraysize);

 28

 29     if(array == NULL)

 30     {

 31         printf("Malloc failed for array size %d \n",arraysize);

 32         exit(-1);

 33     }

 34

 35     for (x=0;x

 36     {

 37         array[x] = (int*) malloc (arraysize*sizeof(int));

 38

 39         if(array[x] == NULL)

 40         {

 41             printf("Failed malloc for array size %d\n",arraysize);

 42             exit(-1);

 43         }

 44     }

 45

 46     exit(0);

 47 }

 

$ gcc -fprofile-arcs -ftest-coverage -g -o sample test.c

$ ./sample 10

Creating an 10 by 10 array

 $ gcov test.c

File ''/usr/include/sys/sysmacros.h''

Lines executed:0.00% of 6

/usr/include/sys/sysmacros.h:creating ''sysmacros.h.gcov''

File ''test.c''

Lines executed:57.89% of 19

test.c:creating ''test.c.gcov''

$ cat test.c.gcov

        -:    0:Source:test.c

        -:    0:Graph:test.gcno

        -:    0:Data:test.gcda

        -:    0:Runs:1

        -:    0:Programs:1

文章出处:

 

 

阅读(4076) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~