您的位置:首页 > 其它

快速使用gcov&lcov构建程序的单元测试

2015-12-23 13:17 423 查看
在软件开发过程中,为了验证代码块功能的完备及健壮性,我们常常会做一些单元测试,验证函数的调用符合预期,再加上gcov、lcov这样的工具,可以生成HTML格式的单元测试结果,极大地提供了可读性。下面以一个动态库的单元测试为例,简述gcov、lcov的用法。

1、代码准备

在“/home/demo”目录下,包括测试代码test.c和被测试代码demo.h、demo.c,如下:



// demo.h
#ifndef DEMO_H
#define DEMO_H

void demo_foo();
void demo_foo2(int i);

#endif /* DEMO_H */

// demo.c
#include <stdio.h>
#include "demo.h"

void demo_foo()
{
printf("%s\n", __func__);
}

void demo_foo2(int i)
{
if (i > 0) {
printf("%s pos\n", __func__);
if (0 == i % 2) {
printf("%s even\n", __func__);
}
else {
printf("%s odd\n", __func__);
}
}
else if (i < 0) {
printf("%s neg\n", __func__);
}
else {
printf("%s zero\n", __func__);
}
}

// test.c
#include <stdio.h>
#include "demo.h"

int main(int argc, char* argv[])
{
printf("%s unit test begin\n", __func__);

demo_foo();
demo_foo2(2);
demo_foo2(1);
demo_foo2(0);
demo_foo2(-1);

printf("%s unit test end\n", __func__);

return 0;
}


demo.c中定义了两个函数,test.c中分别调用了这两个函数进行测试,其中demo_foo2()函数传入了不同的参数以满足100%条件覆盖,这是一个很简单的例子。

2、生成可执行文件

我们的例子测试的是一个动态库,所以先把demo.h/demo.c编译成一个动态库libdemo.so:

gcc -shared -fpic -o libdemo.so demo.h demo.c


然后编译test.c并链接libdemo.so为可执行文件test:

gcc -o test test.c -L. -ldemo


这一步操作生成了libdemo.so和test两个文件:



我们先来运行一下test这个可执行文件,看它能否正确执行。

LD_LIBRARY_PATH=. ./test

main unit test begin
demo_foo
demo_foo2 pos
demo_foo2 even
demo_foo2 pos
demo_foo2 odd
demo_foo2 zero
demo_foo2 neg
main unit test end


从上面的log可以看出,我们的可执行文件test是没有问题的。

3、重新编译动态库

对一个动态库进行单体测试,为了能够生成HTML形式的测试结果,我们使用gcc编译时,还需要添加两个编译参数,“-fprofile-arcs”和“-ftest-coverage”,前者用来生成对应的”.gcda”后缀的数据,后者用来生成对应的”.gcno”后缀的数据,这两种数据是必须的。因为我们要测试的是动态库,所以需要重新编译这个动态库,而没有必要重新编译其它文件,这一点需要注意。

gcc -fprofile-arcs -ftest-coverage -shared -fpic -o libdemo.so demo.h demo.c


这一步重新编译了libdemo.so,并且产生了对应的demo.gcno数据:



4、运行可执行文件

LD_LIBRARY_PATH=. ./test

main unit test begin
demo_foo
demo_foo2 pos
demo_foo2 even
demo_foo2 pos
demo_foo2 odd
demo_foo2 zero
demo_foo2 neg
main unit test end


这一步生成了demo.gcda数据:



5、使用gcov生成.gcov数据

命令:gcov demo.c

生成文件:demo.c.gcov



我们来看看demo.c.gcov文件有什么内容:

cat demo.c.gcov

-:    0:Source:demo.c
-:    0:Graph:demo.gcno
-:    0:Data:demo.gcda
-:    0:Runs:1
-:    0:Programs:1
-:    1:#include <stdio.h>
-:    2:#include "demo.h"
-:    3:
1:    4:void demo_foo()
-:    5:{
1:    6:    printf("%s\n", __func__);
1:    7:}
-:    8:
4:    9:void demo_foo2(int i)
-:   10:{
4:   11:    if (i > 0) {
2:   12:        printf("%s pos\n", __func__);
2:   13:        if (0 == i % 2) {
1:   14:            printf("%s even\n", __func__);
-:   15:        }
-:   16:        else {
1:   17:            printf("%s odd\n", __func__);
-:   18:        }
-:   19:    }
2:   20:    else if (i < 0) {
1:   21:        printf("%s neg\n", __func__);
-:   22:    }
-:   23:    else {
1:   24:        printf("%s zero\n", __func__);
-:   25:    }
4:   26:}


6、使用lcov生成.info数据

lcov -c -d . -o demo.info

Capturing coverage data from .
Found gcov version: 4.8.4
Scanning . for .gcda files ...
Found 1 data files in .
Processing demo.gcda
Finished .info-file creation


-c用来抓取覆盖率数据,-d指定覆盖率数据所在的目录,-o指定生成的目标文件,后缀为.info。这一步生成了demo.info,不过demo.c.gcov文件被自动清理了。



7、最后一步

使用genhtml命令生成html。

genhtml demo.info -o out

Reading data file demo.info
Found 1 entries.
Found common filename prefix "/home"
Writing .css and .png files.
Generating output.
Processing file demo/demo.c
Writing directory view page.
Overall coverage rate:
lines......: 100.0% (13 of 13 lines)
functions..: 100.0% (2 of 2 functions)
branches...: 100.0% (6 of 6 branches)


-o指定html文件存放位置,这里我们把它放置在当前目录的out文件夹中:



打开out目录下的index.html查看结果如下:



点击“demo”目录:



点击“demo.c”文件:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: