使用 Gcov 和 LCOV 对 C/C++ 项目进行代码覆盖测试

发布于 2023-03-16 21:50:07 字数 5665 浏览 168 评论 0

本文分享如何使用 Gcov 和 LCOV 来衡量 C/C++ 项目的代码覆盖率。如果你想了解 Gcov 是如何工作的,或者你需要在以后衡量 C/C++ 项目的代码覆盖率,希望这篇文章对你有用。

问题

我遇到的问题:几十年前的AC/C++项目没有单元测试,只有回归测试,但是你想知道回归测试测试的是什么代码吗?哪些代码未经测试?什么是代码覆盖率?未来自动化测试用例需要在哪些方面进行改进?

没有单元测试可以测量代码覆盖率吗?是的。

C/C++ 的代码覆盖工具

市面上有一些工具可以衡量黑盒测试的代码覆盖率,比如Squish Coco、Bullseye等,它们的原理是在构建产品时插入instrumentation。

我对 Squish Coco 做了一些研究,因为一些未解决的编译问题,我没有为这个昂贵的工具购买许可证。当我再次调查代码覆盖时,我发现 GCC 有一个内置的代码覆盖工具,叫做 Gcov

先决条件

对于那些想使用 Gcov 的人,为了说明它是如何工作的,我准备了一个示例程序,需要在运行程序之前安装 GCC 和 LCOV。

如果你没有环境或者不想安装它,你可以查看这个示例 存储库

注:源代码在 master 分支 master 下,代码覆盖结果 html 在分支下 coverage

# This is the version of GCC and lcov on my test environment.
sh-4.2$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

sh-4.2$ lcov -v
lcov: LCOV version 1.14

Gcov 的工作原理

Gcov工作流程图

主要分为三个步骤:

  1. 向 GCC 编译添加特殊编译选项以生成可执行文件,以及 *.gcno .
  2. 运行(测试)生成的可执行文件,生成 *.gcda 数据文件。
  3. 使用 *.gcno*.gcdagcov 从源代码生成文件,最后生成代码覆盖率报告。

以下是每个步骤的准确完成方式。

1.编译

第一步是编译。编译用到的参数和文件都已经写在 makefile .

make build

点击查看 make 命令的输出

sh-4.2$ make build 
gcc -fPIC -fprofile-arcs -ftest-coverage -c -Wall -Werror main.c
gcc -fPIC -fprofile-arcs -ftest-coverage -c -Wall -Werror foo.c
gcc -fPIC - fprofile-arcs -ftest-coverage -o main main.o foo.o

从输出中可以看出,该程序是使用两个编译选项编译的 -fprofile-arcs-ftest-coverage . 编译成功后,不仅生成了 main.o 文件,还生成了两个 .gcno 文件。

.gcno 记录文件是在添加 GCC 编译选项后生成的, -ftest-coverage 其中包含在编译过程中重建基本块映射和为块分配源代码行号的信息。

2.运行可执行文件

编译后 main 生成可执行文件,运行(测试)如下

./main

点击查看运行 main 时的输出

sh-4.2$ ./main
Start calling foo() ...
when num is equal to 1...
when num is equal to 2...

运行时 main ,结果记录在 .gcda 数据文件中,如果查看当前目录,可以看到 .gcda 生成了两个文件。

$ ls
foo.c  foo.gcda  foo.gcno  foo.h  foo.o  img  main  main.c  main.gcda  main.gcno  main.o  makefile  README.md

.gcda 记录数据文件的产生是因为程序是用 -fprofile-arcs 引入的选项编译的。它包含弧过渡计数、值分布计数和一些摘要信息。

3.生成报告

make report

点击查看生成报告的输出

sh-4.2$ make report
gcov main.c foo.c
File 'main.c'
Lines executed:100.00% of 5
Creating 'main.c.gcov'

File 'foo.c'
Lines executed:85.71% of 7
Creating 'foo.c.gcov'

Lines executed:91.67% of 12
lcov --capture --directory . --output-file coverage.info
Capturing coverage data from .
Found gcov version: 4.8.5
Scanning . for .gcda files ...
Found 2 data files in .
Processing foo.gcda
geninfo: WARNING: cannot find an entry for main.c.gcov in .gcno file, skipping file!
Processing main.gcda
Finished .info-file creation
genhtml coverage.info --output-directory out
Reading data file coverage.info
Found 2 entries.
Found common filename prefix "/workspace/coco"
Writing .css and .png files.
Generating output.
Processing file gcov-example/main.c
Processing file gcov-example/foo.c
Writing directory view page.
Overall coverage rate:
  lines......: 91.7% (11 of 12 lines)
  functions..: 100.0% (2 of 2 functions)

执行 make report 生成 HTML 报告实际上执行了此命令后面的两个主要步骤。

  1. 结合编译运行时生成的 .gcno.gcda 文件,执行 gcov main.c foo.c 生成 .gcov 代码覆盖率文件的命令。
  2. 使用代码覆盖率文件,通过LCOV .gcov 生成可视化代码覆盖率报告 。

生成 HTML 结果报告的步骤如下。

# 1. Generate the coverage.info data file
lcov --capture --directory . --output-file coverage.info
# 2. Generate a report from this data file
genhtml coverage.info --output-directory out

删除所有生成的文件

可以通过执行 make clean 命令删除所有生成的文件。

点击查看 make clean 命令的输出

sh-4.2$ make clean
rm -rf main *.o *.so *.gcno *.gcda *.gcov coverage.info out

代码覆盖率报告

主页以目录结构显示

进入目录后,显示该目录下的源文件

蓝色表示这些语句被覆盖

红色表示未被覆盖的语句

LCOV 支持语句、函数和分支覆盖率指标。

旁注:还有另一个用于生成 HTML 报告的工具,称为 gcovr,它是用 Python 开发的,其报告的显示方式与 LCOV 略有不同。比如lcov以目录结构显示,gcovr 以文件路径显示,和代码结构总是一样的,所以我更喜欢用前者。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

小猫一只

暂无简介

文章
评论
28 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文