为何LCOV需Baseline步骤获正确结果?相关技术疑问解析
为什么LCOV需要执行“Baseline”步骤才能获取“正确”的覆盖率结果?
首先看man lcov中的官方说明:
--initial
捕获初始零覆盖率数据。在运行任何测试用例前,在包含.bb、.bbg或.gcno文件的目录中,结合
-c选项与该参数运行lcov,将生成一份“基线”覆盖率数据文件,其中所有插装代码行的覆盖率均为零。将此文件(通过lcov -a命令)与测试运行后捕获的覆盖率数据文件合并,可确保即便测试期间未加载所有源代码文件,总代码行覆盖率百分比依然准确。
疑问解答
1. “测试期间未加载所有源代码文件”具体指什么?
就是被测项目里,部分源代码对应的编译产物(比如.o目标文件)在测试运行的整个过程中,完全没被操作系统加载到内存里执行。常见场景包括:
- 项目里的某个工具类、辅助模块,当前所有测试用例都没调用其中的任何函数,导致该模块的文件从未被加载
- 库中的可选功能分支、冷门逻辑模块,测试用例完全没覆盖到,对应的代码文件全程未被加载
2. “不正确”的覆盖率百分比是何种情况?
如果跳过基线步骤,lcov只会统计实际被加载执行过的文件里的代码覆盖率,那些完全没被加载的文件会直接被排除在统计范围外,不会计入总覆盖率的分母,导致结果虚高。
举个直观例子:
项目总共有1000行代码,其中200行所在的文件没被测试加载,测试覆盖了已加载的800行里的400行。
- 无基线:lcov只计算800行的覆盖情况,得出**50%**的错误覆盖率
- 有基线:合并基线后,总代码行按1000行计算,覆盖400行,得出**40%**的真实覆盖率
3. 是否涉及被测库的构造函数调用?
当然会涉及这类场景。比如:
- 被测库中有全局对象的构造函数,但测试用例没触发任何用到该对象的逻辑,导致这个构造函数所在的文件没被加载执行
- 库中用
__attribute__((constructor))标记的静态初始化函数,如果测试全程没触发相关模块的加载,这些代码也不会被统计到
如果不做基线,这类未被加载的构造函数代码会被排除在统计外,同样会让覆盖率结果虚高,无法反映真实的测试覆盖情况。
内容的提问来源于stack exchange,提问作者Johannes Schaub - litb
相关产品推荐
相关产品推荐

