Cobertura 覆盖率报告
- 版本:免费、专业、旗舰
- 产品形态:GitLab.com、GitLab 自管版、GitLab 专属版
要使覆盖率分析正常工作,您需要提供一个格式正确的
Cobertura XML 报告给
artifacts:reports:coverage_report。
该格式最初是为 Java 开发的,但现在大多数其他语言和平台的覆盖率分析框架都提供了插件来支持它,例如:
- simplecov-cobertura (Ruby)
- gocover-cobertura (Go)
- cobertura (Node.js)
另一些覆盖率分析框架则原生支持该格式,例如:
- Istanbul (JavaScript)
- Coverage.py (Python)
- PHPUnit (PHP)
配置完成后,如果您的合并请求触发了收集覆盖率报告的流水线,覆盖率信息便会显示在差异视图中。 这包括流水线中任何阶段、任何作业的报告。每行代码的覆盖率显示如下:
covered(绿色):已被测试至少执行一次的代码行no test coverage(橙色):已加载但从未执行的代码行- 无覆盖率信息:未被插桩或未加载的代码行
将鼠标悬停在覆盖率条上可以查看更多信息,例如该行被测试执行的次数。
上传测试覆盖率报告不会自动启用:
您需要单独配置这些功能。
限制
Cobertura 格式的 XML 文件有 100 个 <source> 节点的限制。如果您的 Cobertura 报告超过
100 个节点,合并请求的差异视图中可能会出现匹配错误或无法匹配的情况。
单个 Cobertura XML 文件大小不能超过 10 MiB。对于大型项目,请将 Cobertura XML 文件拆分为 更小的文件。更多详情请参阅 此 issue。 当提交多个文件时,覆盖率在合并请求上显示可能需要几分钟时间。
覆盖率可视化仅在流水线完成后才会显示。如果流水线包含一个 阻塞式手动作业,流水线会等待该手动作业完成后才能继续,因此不被视为已完成。 如果阻塞式手动作业未运行,则无法显示覆盖率可视化。
如果作业生成了多个报告,请在构件路径中使用通配符。
自动类路径修正
只有当 class 元素中的 filename 包含相对于项目根目录的完整路径时,覆盖率报告才能正确匹配已更改的文件。
然而,在某些覆盖率分析框架中,生成的 Cobertura XML 中的 filename 路径是相对于类包目录的,而不是项目根目录。
为了智能地推断出相对于项目根目录的 class 路径,Cobertura XML 解析器会尝试通过以下方式构建完整路径:
- 从
sources元素中提取部分source路径,并与类filename路径结合。 - 检查候选路径是否存在于项目中。
- 使用第一个匹配的候选路径作为类的完整路径。
路径修正示例
例如,一个 C# 项目,其:
-
完整路径为
test-org/test-cs-project。 -
相对于项目根目录的文件如下:
Auth/User.cs Lib/Utils/User.cs -
来自 Cobertura XML 的
sources,其路径格式为<CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/...:<sources> <source>/builds/test-org/test-cs-project/Auth</source> <source>/builds/test-org/test-cs-project/Lib/Utils</source> </sources>
解析器会:
- 从
sources中提取Auth和Lib/Utils,并用它们来确定相对于项目根目录的class路径。 - 将这些提取的
sources与类文件名结合。例如,如果存在一个filename值为User.cs的class元素,解析器会采用第一个匹配的候选路径,即Auth/User.cs。 - 对于每个
class元素,会尝试为每个提取的source路径寻找匹配项,最多迭代 100 次。如果达到此限制仍未在文件树中找到匹配路径,则该类不会包含在最终的覆盖率报告中。
自动类路径修正同样适用于具有以下特征的 Java 项目:
-
完整路径为
test-org/test-java-project。 -
相对于项目根目录的文件如下:
src/main/java/com/gitlab/security_products/tests/App.java -
来自 Cobertura XML 的
sources:<sources> <source>/builds/test-org/test-java-project/src/main/java/</source> </sources> -
class元素,其filename值为com/gitlab/security_products/tests/App.java:<class name="com.gitlab.security_products.tests.App" filename="com/gitlab/security_products/tests/App.java" line-rate="0.0" branch-rate="0.0" complexity="6.0">
自动类路径修正仅对格式为 <CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/... 的 source 路径有效。
如果路径不符合此模式,source 将被忽略。解析器假定 class 元素中的 filename 包含相对于项目根目录的完整路径。
测试覆盖率配置示例
本节提供了不同编程语言的测试覆盖率配置示例。您也可以在
coverage-report 演示项目中查看一个可运行的示例。
JavaScript 示例
以下 .gitlab-ci.yml 示例使用 Mocha
JavaScript 测试框架和 nyc 覆盖率工具来
生成覆盖率构件:
test:
script:
- npm install
- npx nyc --reporter cobertura mocha
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xmlJava 和 Kotlin 示例
Maven 和 Gradle 示例将 JaCoCo 报告转换为 Cobertura 格式。 或者,issue 227345 跟踪了启用原生 JaCoCo 报告支持的工作。
Maven 示例
以下适用于 Java 或 Kotlin 的 .gitlab-ci.yml 示例使用 Maven
来构建项目,并使用 JaCoCo 覆盖率工具来
生成覆盖率构件。
如果您想构建自己的镜像,可以查看 Docker 镜像配置和脚本。
GitLab 期望构件是 Cobertura 格式,因此在上传前您需要执行一些
脚本。test-jdk11 作业负责测试代码并生成一个 XML 构件。
coverage-jdk-11 作业则将该构件转换为 Cobertura 报告:
test-jdk11:
stage: test
image: maven:3.6.3-jdk-11
script:
- mvn $MAVEN_CLI_OPTS clean org.jacoco:jacoco-maven-plugin:prepare-agent test jacoco:report
artifacts:
paths:
- target/site/jacoco/jacoco.xml
coverage-jdk11:
# 所处阶段必须晚于 test-jdk11 的阶段。
# `visualize` 阶段默认不存在。
# 请先定义它,或选择一个现有的阶段,如 `deploy`。
stage: visualize
image: registry.gitlab.com/haynes/jacoco2cobertura:1.0.9
script:
# 使用相对项目路径将报告从 jacoco 转换为 cobertura
- python /opt/cover2cover.py target/site/jacoco/jacoco.xml $CI_PROJECT_DIR/src/main/java/ > target/site/cobertura.xml
needs: ["test-jdk11"]
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: target/site/cobertura.xmlGradle 示例
以下适用于 Java 或 Kotlin 的 .gitlab-ci.yml 示例使用 Gradle
来构建项目,并使用 JaCoCo 覆盖率工具来
生成覆盖率构件。
如果您想构建自己的镜像,可以查看 Docker 镜像配置和脚本。
GitLab 期望构件是 Cobertura 格式,因此在上传前您需要执行一些
脚本。test-jdk11 作业负责测试代码并生成一个 XML 构件。
coverage-jdk-11 作业则将该构件转换为 Cobertura 报告:
test-jdk11:
stage: test
image: gradle:6.6.1-jdk11
script:
- 'gradle test jacocoTestReport' # 必须配置 jacoco 以创建 xml 报告
artifacts:
paths:
- build/jacoco/jacoco.xml
coverage-jdk11:
# 所处阶段必须晚于 test-jdk11 的阶段。
# `visualize` 阶段默认不存在。
# 请先定义它,或选择一个现有的阶段,如 `deploy`。
stage: visualize
image: registry.gitlab.com/haynes/jacoco2cobertura:1.0.7
script:
# 使用相对项目路径将报告从 jacoco 转换为 cobertura
- python /opt/cover2cover.py build/jacoco/jacoco.xml $CI_PROJECT_DIR/src/main/java/ > build/cobertura.xml
needs: ["test-jdk11"]
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: build/cobertura.xmlPython 示例
以下 .gitlab-ci.yml 示例使用 pytest-cov 来收集测试覆盖率数据:
run tests:
stage: test
image: python:3
script:
- pip install pytest pytest-cov
- pytest --cov --cov-report term --cov-report xml:coverage.xml
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xmlPHP 示例
以下适用于 PHP 的 .gitlab-ci.yml 示例使用 PHPUnit
来收集测试覆盖率数据并生成报告。
通过一个最简的 phpunit.xml 文件(您可以参考
此示例仓库),您可以运行测试并
生成 coverage.xml:
run tests:
stage: test
image: php:latest
variables:
XDEBUG_MODE: coverage
before_script:
- apt-get update && apt-get -yq install git unzip zip libzip-dev zlib1g-dev
- docker-php-ext-install zip
- pecl install xdebug && docker-php-ext-enable xdebug
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php --install-dir=/usr/local/bin --filename=composer
- composer install
- composer require --dev phpunit/phpunit phpunit/php-code-coverage
script:
- php ./vendor/bin/phpunit --coverage-text --coverage-cobertura=coverage.cobertura.xml
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.cobertura.xmlCodeception 通过 PHPUnit,也支持使用
run 命令生成 Cobertura 报告。
生成文件的路径取决于 --coverage-cobertura 选项和
单元测试套件的 paths
配置。请配置 .gitlab-ci.yml 以在适当的路径下查找 Cobertura 报告。
C/C++ 示例
以下适用于 C/C++ 并使用 gcc 或 g++ 作为编译器的 .gitlab-ci.yml 示例,使用
gcovr 来生成 Cobertura XML 格式的覆盖率输出文件。
此示例假设:
Makefile是由cmake在build目录中生成的, 该操作在上一阶段的另一个作业中完成。 (如果您使用automake生成Makefile, 则需要调用make check而不是make test。)cmake(或automake)已设置编译器选项--coverage。
run tests:
stage: test
script:
- cd build
- make test
- gcovr --xml-pretty --exclude-unreachable-branches --print-summary -o coverage.xml --root ${CI_PROJECT_DIR}
artifacts:
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
expire_in: 2 days
reports:
coverage_report:
coverage_format: cobertura
path: build/coverage.xmlGo 示例
以下适用于 Go 的 .gitlab-ci.yml 示例使用:
go test来运行测试。gocover-cobertura将 Go 的覆盖率文件转换为 Cobertura XML 格式。
此示例假设正在使用 Go modules。
-covermode count 选项与 -race 标志不兼容。
如果您想在启用 -race 标志的同时生成代码覆盖率,必须切换到
-covermode atomic,它比 -covermode count 慢。更多详情请参阅
此博客文章。
run tests:
stage: test
image: golang:1.17
script:
- go install
- go test ./... -coverprofile=coverage.txt -covermode count
- go get github.com/boumenot/gocover-cobertura
- go run github.com/boumenot/gocover-cobertura < coverage.txt > coverage.xml
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xmlRuby 示例
以下适用于 Ruby 的 .gitlab-ci.yml 示例使用
rspec来运行测试。simplecov和simplecov-cobertura来记录覆盖率文件并创建 Cobertura XML 格式的报告。
此示例假设:
- 正在使用
bundler进行依赖管理。rspec、simplecov和simplecov-coberturagem 已添加到您的Gemfile中。 CoberturaFormatter已添加到您spec_helper.rb文件中的SimpleCov.formatters配置里。
run tests:
stage: test
image: ruby:3.1
script:
- bundle install
- bundle exec rspec
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/coverage.xml故障排除
未显示测试覆盖率可视化
如果差异视图中未显示测试覆盖率可视化,您可以检查 覆盖率报告本身,并确认以下几点:
- 您在差异视图中查看的文件在覆盖率报告中被提及。
- 报告中的
source和filename节点遵循预期的结构,以匹配您仓库中的文件。 - 流水线已完成。如果流水线被手动作业阻塞,则不被视为已完成。
- 覆盖率报告文件未超出限制。
报告构件默认不可下载。如果您希望报告可以从作业详情页面下载,请将您的覆盖率报告添加到构件 paths 中:
artifacts:
paths:
- coverage/cobertura-coverage.xml
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml