前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >代码覆盖率--gcov/lcov/gcovr

代码覆盖率--gcov/lcov/gcovr

作者头像
用户5521279
发布2019-07-24 14:40:30
9.4K0
发布2019-07-24 14:40:30
举报
文章被收录于专栏:搜狗测试搜狗测试

统计C/C++代码覆盖率的工具很多,比如OpenCppCoverage可以与VS工具配合,获取并展示代码覆盖率简单直观,但是在Linux、Mac等系统该如何统计呢?一般的持续集成工具(Jenkins、gitlab-ci等)中又该如何统计呢?

准备工具

请参考教程安装即可:

  • GCC
  • CMake
  • Google Test
  • gcov
  • lcov
  • gcovr

代码覆盖率

代码覆盖率一般包含以下几种类型:

  • 函数覆盖率:描述有多少比例的函数经过了测试。
  • 语句覆盖率:描述有多少比例的语句经过了测试。
  • 分支覆盖率:描述有多少比例的分支(例如:if-else,case语句)经过了测试。
  • 条件覆盖率:描述有多少比例的可能性经过了测试。

因此一般的覆盖率结果也分为几种不同的类型。

gcov

gcov是由gcc工具链提供的代码覆盖率生成工具,可以很方便的和GCC编译器配合使用,通常情况下,直接安装gcc工具链,也就同时包含了gcov命令行工具。

对于代码覆盖率工具所做的工作,可以简单的理解为:标记一次运行过程中,哪些代码被执行过,哪些没有执行。 因此,即便没有测试代码,直接运行编译产物也可以得到代码的覆盖率。只不过,通常情况下这样得到的覆盖率较低罢了。

在项目中我们使用cmake编译,因此在CMakeLists.txt文件中设置覆盖率相关参数。

代码语言:javascript
复制
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")

将-fprofile-arcs -ftest-coverage添加到编译器flag中,这个参数是很重要的,是生成代码覆盖率所必须的,对于该参数的说明可以参考:https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#Instrumentation-Options

执行cmake、make命令编译之后生成单测可执行文件Test。执行单测:

代码语言:javascript
复制
./Test --gtest_filter=ClassName.CaseName

单测执行之后,我们会得到每个源码文件对应的gcda和gcno后缀文件,比如main函数所在的主文件TestMain.cpp,通过TestMain.cpp.gcda和TestMain.cpp.gcno两个文件,便可以得到代码TestMain.cpp的覆盖率结果了。

通过gcov指定源码文件的名称,便可以得到该源码文件的覆盖率结果:

代码语言:javascript
复制
gcov TestMain.cpp.gcno
lcov

gcov得到的结果是文本形式的,而且不同的源码文件需要一一执行gcov命令,对于大工程是不方便的,我们希望得到更加美观和便于浏览的结果。

lcov是gcov工具的图形前端,收集多个源文件的gcov数据,生成描述覆盖率的HTML页面。生成的结果中会包含概述页面,方面浏览。

lcov有很多参数配合使用可以满足各种需求,lcov的使用方法可以通过以下这条命令查询:

代码语言:javascript
复制
lcov --help

我们一般关注以下这几个参数:

  • -c 或者 --capture 指定从编译产物中收集覆盖率信息。
  • -d DIR 或者 --directory DIR 指定编译产物的路径。
  • -e FILE PATTERN 或者 --extract FILE PATTERN 从指定的文件中根据PATTERN过滤结果。
  • -o FILENAME 或者 --output-file FILENAME 指定覆盖率输出的文件名称。

此外,特殊说明:

  • lcov默认不会打开分支覆盖率,因此我们还需要增加这个参数来打开分支覆盖率的计算: --rc lcov_branch_coverage=1
  • lcov输出的仍然是一个中间产物,我们还需要通过lcov软件包提供的另外一个命令genhtml来生成最终需要的html格式的覆盖率报告文件。 同样的,为了打开分支覆盖率的计算,我们也要为这个命令增加--rc lcov_branch_coverage=1参数

最后,我们编辑一个make_all.sh脚本执行lcov相关操作:

代码语言:javascript
复制
COVERAGE_FILE=coverage.info
REPORT_FOLDER=coverage_report
lcov --rc lcov_branch_coverage=1 -c -d . -o ${COVERAGE_FILE}_tmp
lcov --rc lcov_branch_coverage=1  -e ${COVERAGE_FILE}_tmp "*src*" -o ${COVERAGE_FILE}
genhtml --rc genhtml_branch_coverage=1 ${COVERAGE_FILE} -o ${REPORT_FOLDER}

代码解析:

我们从前面的编译结果中收集覆盖率结果,并将结果输出到coverage.info_tmp文件中,该文件存储在当前目录下。但是这里面会包含非项目源码的覆盖率(例如GoogleTest),所以我们通过另外一条命令指定"src"文件夹进行过滤。最后,通过genhtml得到HTML格式的报告,报告结果存储在文件夹coverage_report中。

gcovr

一般场景下使用gcov和lcov能满足代码覆盖率的获取和展示工作,lcov和genhtml配合生成的HTML报告内容详尽,简洁直观,行覆盖率、分支覆盖率都有,但是HTML文件在常用的持续集成工具(比如Jenkins、gitlab-ci)中均无法集成,因此我们需要其他的工具用于覆盖率结果的持续集成展示。

gcovr是一款针对C/C++代码覆盖率并支持以多种方式(包括列表方式、XML文件方式、HTML网页方式等)展示出来的工具,而XML文件刚好是可以被持续集成工具解析的。

gcovr有很多参数配合使用可以满足各种需求,gcovr的使用方法可以通过以下这条命令查询:

代码语言:javascript
复制
gcovr --help

我们一般关注以下这几个参数:

  • -r ROOT 或者 --root ROOT 代码根目录,默认为'.',当前的路径。
  • -b 或者 --branches 以分支覆盖率形式报告。
  • -x 或者 --xml 指定报告的形式为XML。
  • -o OUTPUT 或者 --output OUTPUT 指定覆盖率输出的文件名称。
  • --html 指定报告的形式为HTML。

在项目的编译根目录下使用如下命令:

代码语言:javascript
复制
gcovr -r . --xml -o coverage.xml

当前目录下生成coverage.xml文件详细记录了所有源码文件的行覆盖率信息。

常见问题:gcovr得到的覆盖率为0%

解决:执行gcovr -r . 命令一般在编译路径下,cmake项目中我们一般习惯创建一个build文件夹编译源文件,测试执行之后,build路径下包含gcda和gcno、cpp.o,其实执行gcovr命令还需要源码文件,因此,需要在上层根目录下执行gcovr。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 搜狗测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备工具
  • 代码覆盖率
    • gcov
      • lcov
        • gcovr
          • 常见问题:gcovr得到的覆盖率为0%
      相关产品与服务
      持续集成
      CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档