快速使用gcov&lcov构建程序的单元测试
2015-12-23 13:17
423 查看
在软件开发过程中,为了验证代码块功能的完备及健壮性,我们常常会做一些单元测试,验证函数的调用符合预期,再加上gcov、lcov这样的工具,可以生成HTML格式的单元测试结果,极大地提供了可读性。下面以一个动态库的单元测试为例,简述gcov、lcov的用法。
demo.c中定义了两个函数,test.c中分别调用了这两个函数进行测试,其中demo_foo2()函数传入了不同的参数以满足100%条件覆盖,这是一个很简单的例子。
然后编译test.c并链接libdemo.so为可执行文件test:
这一步操作生成了libdemo.so和test两个文件:
我们先来运行一下test这个可执行文件,看它能否正确执行。
从上面的log可以看出,我们的可执行文件test是没有问题的。
这一步重新编译了libdemo.so,并且产生了对应的demo.gcno数据:
这一步生成了demo.gcda数据:
生成文件:demo.c.gcov
我们来看看demo.c.gcov文件有什么内容:
-c用来抓取覆盖率数据,-d指定覆盖率数据所在的目录,-o指定生成的目标文件,后缀为.info。这一步生成了demo.info,不过demo.c.gcov文件被自动清理了。
-o指定html文件存放位置,这里我们把它放置在当前目录的out文件夹中:
打开out目录下的index.html查看结果如下:
点击“demo”目录:
点击“demo.c”文件:
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”文件:
相关文章推荐
- jsp页面展现swf文件 实例详解
- 浏览器页面加载解析渲染机制(一)
- 55.动态加载Html
- 使用replace和strip函数删除open()函数独处的回车问题
- 56.Java与js交互
- 57.动态添加子View(Java/XML两种方式)
- 58.圆角图片
- 使用 Cloud Insight SDK 监控北京空气质量!
- 安装jar包到本地maven仓库
- ZOJ Problem Set - 2554 Brownie Points
- USACO 4.2.1 草地排水 网络流
- 信息系统开发与管理总结
- Jar包可执行??
- 59.仿微信的图片浏览器
- 利用@media screen实现网页布局的自适应
- 使用 Cloud Insight SDK 监控北京空气质量!
- 控制双端通用链表
- 构造函数中慎用memset
- 【编译原理】:如何通过正规式写DFA
- 数据泵导出/导入Expdp/impdp