CMake编译项目集成Gcov/Lcov代码覆盖率测试

原文链接:http://blog.yeyuzhen.cn/?p=203

       脑补链接:什么是CMake? 什么是代码覆盖率测试? 什么是 Gcov?

       最近不怎么顺利的面试经历,让我觉得自己其实是一个2B程序员。应该是懒的原因,涉及到某技术的实现原理啥的,就觉得很烦人。能用就好,何必执着?所以,一个技术问题下来,都是“晚节不保”。自己更关心的是诸如“如何细粒度化任务,以提高开发效率?”、“如何实践代码覆盖率测试,提高程序的鲁棒性?”这类问题。唉~貌似逼格(项目经理)和现实(程序员)存在不小的差距。

       日常开发中,我就很注重测试的环节——功能测试、性能测试。我常和组员说,“代码写的不好可以慢慢学,但是测试一定要用心,程序是一点点测出来的”,“能测出来的问题,不算Bug”。但是经过长期的“感性”测试,不免问自己,“测这些用例就OK了?”、“这块代码有没有问题?”、“测试要如何度量?”。后来了解到“代码覆盖率测试”这么个好东西,可以初步解决测试度量的问题。

完整演示项目Github地址:CMakeGcovSupport

初始项目目录结构:
CMakeGcovSupport
├── CMakeLists.txt
├── bin
├── build
├── include
│   └── name.h
├── libgreeting
│   ├── CMakeLists.txt
│   ├── include
│   │   └── greeting.h
│   └── src
│       ├── CMakeLists.txt
│       ├── greeting.cpp
│       └── yelp.cpp
└── src
    ├── CMakeGcovSupport.cpp
    ├── CMakeLists.txt
    └── name.cpp

       示例程序是个很简单的输出一行问候语的程序。为了演示复杂目录结构下CMake集成Gcov的方法,故意将输出问候语的函数单独放到了 libgreeting 静态库中。执行如下编译命令:

$ cd CMakeGcovSupport
$ mkdir build
$ cd build
$ cmake -DENABLE_COVERAGE=ON ..
$ gmake all

执行 CMake 外部编译之后,CMake 在 build 目录内为我们生成了 .gcno 文件:

CMakeGcovSupport
├── CMakeLists.txt
├── bin
│   └── CMakeGcovSupport
├── build
│   ├── ......
│   ├── libgreeting
│   │   ├── ......
│   │   └── src
│   │       ├── CMakeFiles
│   │       │   ├── ......
│   │       │   ├── greeting.dir
│   │       │   │   ├── ......
│   │       │   │   ├── greeting.cpp.gcno
│   │       │   │   ├── greeting.cpp.o
│   │       │   │   ├── ......
│   │       │   │   ├── yelp.cpp.gcno
│   │       │   │   └── yelp.cpp.o
│   │       │   └── ......
│   │       └── ......
│   └── src
│       ├── CMakeFiles
│       │   ├── ......
│       │   ├── CMakeGcovSupport.dir
│       │   │   ├── CMakeGcovSupport.cpp.gcno
│       │   │   ├── CMakeGcovSupport.cpp.o
│       │   │   ├── ......
│       │   │   ├── name.cpp.gcno
│       │   │   ├── name.cpp.o
│       │   │   └── ......
│       │   └── progress.marks
│       └── ......
├── include
├── libgreeting
└── src

为了避免接下来执行程序过程中,未覆盖的源码文件的覆盖率信息丢失,我们需要对覆盖率信息进行初始化操作:

$ cd CMakeGcovSupport
$ lcov -d build -z
$ lcov -d build -b . --no-external --initial -c -o CMakeGcovSupportInitialCoverage.info

然后我们执行 bin 中的 CMakeGcovSupport, main() 函数中将会调用 Greeting() 和 Name()  函数,而不会调用到 Yelp() 函数。

$ cd CMakeGcovSupport
$ cd bin
$ ./CMakeGcovSupport
$ Hello, gcov.

这时,我们去 .gcno 所在目录,会看到有同名的 .gcda 覆盖率数据文件生成了。执行以下命令,生成覆盖率测试报告:

$ cd CMakeGcovSupport
$ lcov -d build -b . --no-external -c -o CMakeGcovSupportCoverage.info
$ genhtml -o CMakeGcovSupportCoverageReport --prefix=`pwd` CMakeGcovSupportInitialCoverage.info CMakeGcovSupportCoverage.info

用浏览器打开 CMakeGcovSupportCoverageReport 目录中的 index.html 查看覆盖率报告(Mac + Lcov1.10):

Linux + Lcov1.11覆盖率结果(不会误包含外部头文件覆盖率信息):

       以上就是CMake项目初步集成 Gcov/Lcov 的方式。但是,还未深度集成到 CMake 编译过程中,而且覆盖率报告还存在一些瑕疵。下一步计划解决应用“--no-external”选项之后依旧会包含外部头文件覆盖率信息的问题,以及不显示头文件覆盖率信息的问题。最终深度集成 CMake 的效果希望是自定义如下命令:

$ gmake InitialCoverage   # 初始化覆盖率信息命令
$ gmake ReportCoverage  # 生成覆盖率测试报告命令

 

参考

[1] 测试覆盖(率)到底有什么用?

[2] Linux 下 C/C++ 项目代码覆盖率的产生方法

[3] User Manuals - lcov

[4] gcov lcov 覆盖 c/c++ 项目入门

 [5] 使用gcov,lcov,genhtml进行代码覆盖率测试

[6] 关于C++ code coverage tool 的研究(1)

[7] 关于C++ code coverage tool 的研究(2)—GCOV 实现原理

[8] 关于C++ code coverage tool 的研究(3)—gcov使用实例

[9] CMake添加gcov代码覆盖测试支持

[10] Linux平台代码覆盖率测试工具GCOV简介

编辑历史:

       V1.1,增加 Linux + Lcov1.11 下覆盖率报告截图,@2014-11-09

       V1.0,初稿,@2014-11-08 

你可能感兴趣的:(C++,C,C++,CMake,覆盖率测试,lcov)