代码覆盖率

什么是代码覆盖率?

代码覆盖率本质上衡量的是在运行某个测试时,程序中某些代码行被执行的频率、分支被选择的频率或条件被满足的频率。

在讨论代码覆盖率时,需要注意两件非常重要的事情

  • 如果在运行测试时,某个代码分支根本没有被执行,那么这些测试将永远无法发现此特定代码段中的错误。

  • 如果某个代码分支被执行(即使执行频率很高),这仍然不能明确表明**测试的质量**。可能是测试执行了代码,但实际上并没有检查代码是否**正确**执行。

总之,我们可以使用代码覆盖率来查找需要(更多)测试的区域,但我们不能用它来确认某些区域是否经过了充分测试。

Firefox 代码覆盖率报告

我们自动在所有 mozilla-central 运行(针对 Linux 和 Windows)上运行代码覆盖率构建和测试。支持 C/C++、Rust 和 JavaScript。

生成的报告可以在 https://coverage.moz.tools/ 找到。报告可以按平台和/或测试套件进行筛选。

我们还会生成所有完全未覆盖文件的报告,可以在 https://coverage.moz.tools/#view=zero 找到。您可以使用它来查找应该测试的代码区域,或不再使用的代码(死代码,可以删除)。

Firefox 上的 C/C++ 代码覆盖率

有几种方法可以获取 mozilla-central 的 C/C++ 覆盖率信息,包括创建您自己的覆盖率构建。接下来的部分描述了可用的选项。

从 Try 构建(或任何其他 CI 构建)生成代码覆盖率报告

要启动代码覆盖率构建,您需要选择 linux64-ccov 平台(使用 –full 时使用模糊选择器,以便 ccov 构建显示)。

例如,对于 Try 构建

./mach try fuzzy -q 'linux64-ccov'

现在有两个选项,您可以选择本地生成报告或使用一键式 Loaner。

使用一键式 Loaner 生成报告

在 Treeherder 上选择 B 作业并获取一键式 Loaner。

在 Loaner 中,下载并执行脚本 https://github.com/mozilla/code-coverage/blob/master/report/firefox_code_coverage/codecoverage.py

wget https://raw.githubusercontent.com/mozilla/code-coverage/master/report/firefox_code_coverage/codecoverage.py
python codecoverage.py

此命令将自动在您当前工作目录的**report**子目录中生成代码覆盖率信息的 HTML 报告。

本地生成报告

先决条件

  • 创建一个新的 virtualenv 并激活它,然后运行

pip install firefox-code-coverage

给定一个 Treeherder linux64-ccov 构建(及其分支,例如`mozilla-central`或`try`,以及修订版本,您推送的顶端提交哈希),运行以下命令

firefox-code-coverage PATH/TO/MOZILLA/SRC/DIR/ BRANCH REVISION

此命令将自动从 Treeherder 构建下载代码覆盖率工件,并生成代码覆盖率信息的 HTML 报告。该报告将存储在您当前工作目录的**report**子目录中。

创建您自己的覆盖率构建

在 Linux、Windows 和 Mac OS X 上,使用 GCC 或 Clang 生成检测构建非常简单。将以下几行添加到您的.mozconfig文件中应该就足够了

# Enable code coverage
ac_add_options --enable-coverage

# Needed for e10s:
# With the sandbox, content processes can't write updated coverage counters in the gcda files.
ac_add_options --disable-sandbox

可能需要一些其他选项,请检查 CI 上使用的代码覆盖率 mozconfigs 以确保:browser/config/mozconfigs/linux64/code-coverage、browser/config/mozconfigs/win64/code-coverage、browser/config/mozconfigs/macosx64/code-coverage。

确保您没有启用 工件构建,因为它可能会阻止创建覆盖率工件。

然后,您可以照常创建构建。构建完成后,您可以运行任何想要运行的测试/工具,覆盖率数据会自动写入特殊文件。为了查看/处理此数据,我们建议使用 grcov 工具,这是一个管理和可视化 gcov 结果的工具。您也可以使用之前针对 CI 构建解释的相同过程。

调试 Try 服务器上的失败测试

当通过推送到 Try 运行代码覆盖率时,创建的所有数据都会被 ActiveData 摄取并处理成不同的数据格式以供分析。每当代码覆盖率运行生成 *.gcda 和 *.gcno 文件时,ActiveData 就会开始工作。现在,有时,当测试在使用 GCOV 检测的构建上运行时,它会永久失败。为了调试这些问题,而不会用垃圾覆盖率数据过载 ActiveData,请打开文件 taskcluster/gecko_taskgraph/transforms/test/__init__.py 并添加以下行,

test['mozharness'].setdefault('extra-options', []).append('--disable-ccov-upload')

紧跟在以下代码行之后

test['mozharness'].setdefault('extra-options', []).append('--code-coverage')

现在,当您推送到 Try 调试某些失败的测试或其他任何内容时,不会从构建机器或测试机器上传任何代码覆盖率工件。

Firefox 上的 JS 调试器每个测试代码覆盖率

有两种方法可以获取 mozilla-central 的 JavaScript 每个测试代码覆盖率信息。接下来的部分描述了这些选项。

从 Try 构建(或任何其他 Treeherder 构建)生成每个测试代码覆盖率

要启动代码覆盖率构建,您需要选择 linux64-jsdcov 平台。例如,对于 Try 构建

./mach try fuzzy -q 'linux64-jsdcov'

这会生成 JavaScript 对象表示法 (JSON) 文件,这些文件可以从 Treeherder 测试机器下载并在本地进行处理或分析。

本地生成每个测试代码覆盖率

要在本地生成包含覆盖率信息的 JSON 文件,只需添加一个名为--jscov-dir-prefix的额外参数,该参数接受目录作为输入并将结果数据存储在该目录中。例如,要收集整个 Mochitest 套件的代码覆盖率

./mach mochitest --jscov-dir-prefix /PATH/TO/COVERAGE/DIR/

目前,只有 Mochitest 和 Xpcshell 测试套件具有此功能。