我正在使用gcov来测量我的C ++代码中的覆盖率。我希望得到100%的覆盖率,但是由于存在一些理论上无法触及的代码行(需要实现但从未被调用的方法,{{1的默认分支)这一事实而受到阻碍语句等)。这些分支中的每一个都包含switch
语句,但gcov仍然将它们标记为未命中。
我希望能够告诉gcov忽略这些分支。有没有办法给gcov这些信息 - 通过注释源代码或任何其他机制?
答案 0 :(得分:33)
请使用lcov。它隐藏了gcov的复杂性,产生了良好的输出,允许每次测试的详细输出,具有简单的文件过滤功能,以及已经评估的线路的ta-taa线标记:
来自geninfo(1):
geninfo识别以下标记:
- LCOV_EXCL_LINE
- 将排除包含此标记的行。
- LCOV_EXCL_START
- 标记排除部分的开头。当前行是本节的一部分。
- LCOV_EXCL_STOP
- 标记排除部分的结尾。当前行不属于本节的一部分。
答案 1 :(得分:3)
名为gcovr的工具可用于汇总gcov的输出,并且(from at least version 3.4)支持与lcov相同的排除标记。
来自this answer:
geninfo可以识别以下标记:
- LCOV_EXCL_LINE
- 包含该标记的行将被排除。
- LCOV_EXCL_START
- 标记被排除部分的开头。当前行是本节的一部分。
- LCOV_EXCL_STOP
- 标记排除部分的结尾。当前行不属于本节。
您也可以将以上'LCOV'
替换为'GCOV'
或'GCOVR'
。他们都工作。
答案 2 :(得分:1)
你能介绍一下相关函数的单元测试吗?这些测试只是为了通过直接攻击理论上不可靠的代码路径来关闭gcov?由于它们是单元测试,它们可能忽略了情况的“不可能性”。他们可以调用从未调用过的函数,传递无效的枚举值来捕获默认分支等等。
然后,只在使用NDEBUG编译的代码版本上运行这些测试,或者在测试断言被触发的工具中运行它们 - 无论您的测试框架支持什么。
我觉得有点奇怪的是规范说代码必须在那里,而不是包含代码功能要求的规范。特别是,这意味着您的测试不会测试这些要求,这是保持要求正常运行的理由。就个人而言,我想要修改规范,“如果使用无效的枚举值调用,函数将失败assert
。调用者不应在释放模式下使用无效的枚举值调用该函数”。或者其他一些。
据推测,它目前所说的是“所有switch语句必须具有默认情况”。但这意味着编码标准通过引入死代码来干扰可观察的行为(至少在gcov下可观察到)。编码标准不应该这样做,因此功能规范应尽可能考虑编码标准。
如果做不到这一点,你可以在#if !GCOV_BUILD
中包装unhittable代码,并为gcov的好处做一个单独的构建。这个构建将失败一些要求,但是在你对代码的分析是正确的条件下,它会让你有信心测试套件测试其他所有东西。
编辑:你说你正在使用一个狡猾的代码生成器,但你也要通过注释源代码来寻求解决方案。如果您要更改源代码,您可以在很多情况下删除死代码吗?并非改变生成的源是理想的,但需要......
答案 3 :(得分:0)
我不相信这是可能的。 Gcov依靠gcc生成额外的代码来生成覆盖输出。 GCov本身只是解析数据。这意味着Gcov无法比gcc更好地分析代码(我假设您使用-Wall并删除了报告为无法访问的代码)。
请记住,可以从任何地方调用可重定位函数,甚至可能是外部dll或可执行文件,因此编译器无法知道将不会调用哪些可重定位函数或这些函数可能具有哪些输入。
您可能需要使用一些简单的静态分析工具来获取所需的信息。