无法使用 lcov 生成覆盖率报告

Cannot generate coverage report using lcov

我正在尝试使用 lcov 为我的单元测试套件生成覆盖率报告,但我什至无法捕获跟踪文件。错误消息表明找不到源文件。代码由构建机器上的 Jenkins 作业编译,单元测试作为目标机器上的下游作业执行。源代码和 gcno 文件被传输到下游作业,然后执行对 lcov 的调用。下面是所有的细节,可能需要一杯咖啡。

在build机器上,make在

中执行
/var/lib/jenkins/workspace/App-Coverage/BUILD/app/

我要覆盖的源代码在

的子目录中
/var/lib/jenkins/workspace/App-Coverage/BUILD/app/packages/

目标文件和gcno文件生成在对应cpp文件的子目录o中。例如

/var/lib/jenkins/workspace/App-Coverage/BUILD/app/packages/subdir/Myclass.cpp
/var/lib/jenkins/workspace/App-Coverage/BUILD/app/packages/subdir/o/Myclass.o
/var/lib/jenkins/workspace/App-Coverage/BUILD/app/packages/subdir/o/Myclass.gcno

源文件和 gcno 文件被复制到单元测试机器,保持相同的文件夹结构并最终在

/var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/

Note: There is a difference in the name of the workspace folder, "App-Coverage-Unittest" instead of "App-Coverage" since these two Jenkins jobs cannot have the same name.

例如现在有

/var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/packages/subdir/Myclass.cpp
/var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/packages/subdir/o/Myclass.o
/var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/packages/subdir/o/Myclass.gcno

单元测试在

中执行
/opt/app/test/app

使用 GCOV_PREFIX_STRIP 和 GCOV_PREFIX 我使 gcda 文件出现在与 gcno 文件相同的文件夹中,例如

/var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/packages/subdir/o/Myclass.gcno
/var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/packages/subdir/o/Myclass.gcda

现在我想使用 lcov 生成覆盖率报告,但我似乎不明白如何正确设置路径。以下示例由 Jenkins 单元测试作业从 /var/lib/jenkins/workspace/App-Coverage-Unittest/ 执行。

例如我试过

lcov -d BUILD/app/packages/ -c --no-external -o app.info -b /var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/

推理:“-d BUILD/app/packages/”是我想要覆盖的内容,“-b /var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/app/”是我执行 make 的项目的根(但在具有不同工作区名称的构建机器上...)。

我也试过了

lcov -d BUILD/app/packages/ --capture --no-external --output-file app.info

推理:“-d BUILD/app/packages/”是我想要覆盖的内容,不要设置 -b 因为每个 gcno/gcda 和相应源文件之间的相对路径与构建机器,也许 lcov 可以弄清楚。

在这两种情况下都会出现类似 "Cannot open source file /var/lib/jenkins/workspace/App-Coverage/BUILD/app/packages/subdir/Myclass.cpp" 的错误 注意:此路径中的工作区文件夹是构建机器的文件夹,而不是单元测试机器的文件夹。我认为这就是 -b 选项旨在解决的问题。显然,这是非常可疑和有价值的线索。 我也收到类似 "Cannot open source file ../../../packages/subdir/Myclass.h" 的错误,我想这与我如何包含头文件有关。

我试过在此处指定所有路径。是否可以使用 lcov 在单元测试作业的工作区中生成覆盖率报告,就像我在这里尝试做的那样?如果是,为 lcov -d 和 -b 标志指定的正确路径是什么?如果不是,我需要更改什么才能使其正常工作?

幸运的是,答案是肯定的,这是可能的。我收到了 lcov 开发人员的回复,为我提供了解决方案,谢谢 Peter!

他指出,所有源代码路径在编译步骤中都被硬编码到 .gcno 文件中。然而,尽管没有找到源文件(并产生警告),lcov 将生成代码覆盖率输出,即使无法找到源代码,仅基于 .gcda 和 .gcno 文件中的数据。但是,genhtml 步骤将失败,因为它无法找到要使用代码覆盖率数据进行注释的源代码。

解决方案是使用 lcov 的 "geninfo_adjust_src_path" 配置设置。通过使用此设置,指示 lcov 在写入输出 .info 文件时将 .gcno 文件中找到的源代码路径更改为正确的源代码路径。所以就我而言:

lcov -d BUILD/app/packages/ --capture --no-external --output-file app.info
     --rc geninfo_adjust_src_path="/var/lib/jenkins/workspace/App-Coverage/BUILD/ 
     => /var/lib/jenkins/workspace/App-Coverage-Unittest/BUILD/"

调用 lcov 时警告 "Cannot open source file" 仍然存在,但生成的 .info 文件将包含正确的路径,因此可以在测试机器上使用 genhtml 转换为 HTML。