Help us learn about your current experience with the documentation. Take the survey.

单元测试报告

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

单元测试报告直接在合并请求和流水线详情中显示测试结果,这样您无需搜索作业日志即可识别失败。

当您需要以下功能时,请使用单元测试报告:

  • 在合并请求中立即查看测试失败。
  • 比较分支之间的测试结果。
  • 使用错误详细信息和屏幕截图调试失败的测试。
  • 随时间推移跟踪测试失败模式。

单元测试报告需要 JUnit XML 格式,并且不会影响作业状态。 要使作业在测试失败时失败,您作业的 script 必须以非零状态退出。

GitLab Runner 将您的 JUnit XML 格式的测试结果作为 artifacts 上传。 当您进入合并请求时,您的测试结果会在源分支(head)和目标分支(base)之间进行比较,以显示更改内容。

文件格式和大小限制

单元测试报告必须使用具有特定要求的 JUnit XML 格式,以确保正确解析和显示。

文件要求

您的测试报告文件必须:

  • 使用带有 .xml 文件扩展名的 JUnit XML 格式。
  • 每个文件小于 30 MB。
  • 作业中所有 JUnit 文件的总大小小于 100 MB。

如果您有重复的测试名称,则仅使用第一个测试,其他同名测试将被忽略。

有关测试用例限制,请参阅 每个单元测试报告的最大测试用例数

JUnit XML 格式规范

GitLab 从您的 JUnit XML 文件中解析以下元素和属性:

XML 元素 XML 属性 描述
testsuite name 测试套件名称(已解析,但不在 UI 中显示)
testcase classname 测试类或类别名称(用作套件名称)
testcase name 单个测试名称
testcase file 定义测试的文件路径
testcase time 测试执行时间(以秒为单位)
failure 元素内容 失败消息和堆栈跟踪
error 元素内容 错误消息和堆栈跟踪
skipped 元素内容 跳过测试的原因
system-out 元素内容 系统输出和附件标签(仅从 testcase 元素解析)
system-err 元素内容 系统错误输出(仅从 testcase 元素解析)

testcase classname 属性用作套件名称,而不是 testsuite name 属性。

XML 结构示例

<testsuites>
  <testsuite name="Authentication Tests" tests="1" failures="1">
    <testcase classname="LoginTest" name="test_invalid_password" file="spec/auth_spec.rb" time="0.23">
      <failure>Expected authentication to fail</failure>
      <system-out>[[ATTACHMENT|screenshots/failure.png]]</system-out>
    </testcase>
  </testsuite>
</testsuites>

此 XML 在 GitLab 中显示为:

  • 套件:LoginTest(来自 testcase classname
  • 名称:test_invalid_password(来自 testcase name
  • 文件:spec/auth_spec.rb(来自 testcase file
  • 时间:0.23s(来自 testcase time
  • 屏幕截图:在测试详情对话框中可用(来自 testcase system-out
  • 未显示:“Authentication Tests”(来自 testsuite name

测试结果类型

测试结果会在合并请求的源分支和目标分支之间进行比较,以显示更改内容:

  • 新失败的测试:在目标分支上通过但在您的分支上失败的测试。
  • 新遇到的错误:在目标分支上通过但在您的分支上出错的测试。
  • 现有失败:在两个分支上都失败的测试。
  • 已解决的失败:在目标分支上失败但在您的分支上通过的测试。

如果无法比较分支(例如,当还没有目标分支数据时),则仅显示您分支上的失败测试。

对于过去 14 天内在默认分支中失败的测试,您会看到类似 Failed {n} time(s) in {default_branch} in the last 14 days 的消息。 此计数包括已完成流水线中的失败测试,但不包括 blocked pipelines。 对 blocked pipelines 的支持已在 issue 431265 中提出。

配置单元测试报告

配置单元测试报告以在合并请求和流水线中显示测试结果。

要配置单元测试报告:

  1. 配置您的测试作业以输出 JUnit XML 格式的测试报告。 有关配置详细信息,请查看您的测试框架文档。
  2. 在您的 .gitlab-ci.yml 文件中,将 artifacts:reports:junit 添加到您的测试作业中。
  3. 指定您的 XML 测试报告文件的路径。
  4. 可选。要使报告文件可浏览,请使用 artifacts:paths 包含它们。
  5. 可选。要在作业失败时也上传报告,请使用 artifacts:when:always

使用 RSpec 的 Ruby 示例配置:

ruby:
  stage: test
  script:
    - bundle install
    - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml
  artifacts:
    when: always
    paths:
      - rspec.xml
    reports:
      junit: rspec.xml

您可以查看测试结果:

  • 在您的测试作业完成后,在流水线详情的 Tests 标签页中。
  • 在您的流水线完成后,在合并请求的 Test summary 面板中。

在合并请求中查看测试结果

在合并请求中查看有关测试失败的详细信息。

Test summary 面板显示您的测试结果概览,包括有多少测试失败和通过。

展开的 Test summary 面板,显示一个失败的测试,并带有 View details 链接

要查看测试失败详情:

  1. 在合并请求中,转到 Test summary 面板。
  2. 要展开 Test summary 面板,请选择 Show details ( chevron-lg-down )。
  3. 选择失败测试旁边的 View details

该对话框显示测试名称、文件路径、执行时间、屏幕截图附件(如果已配置)和错误输出。

要查看所有测试结果:

  • Test summary 面板中,选择 Full report 以转到流水线详情中的 Tests 标签页。

复制失败的测试名称

复制测试名称以在本地重新运行它们进行调试。

先决条件:

  • 您的 JUnit 报告必须包含失败测试的 <file> 属性。

要复制所有失败的测试名称:

  • Test summary 面板中,选择 Copy failed tests ( copy-to-clipboard )。

失败的测试会作为以空格分隔的字符串被复制。

要复制单个失败的测试名称:

  1. 要展开 Test summary 面板,请选择 Show details ( chevron-lg-down )。
  2. 选择您要复制的测试旁边的 View details
  3. 在对话框中,选择 Copy test name to rerun locally ( copy-to-clipboard )。

测试名称已复制到您的剪贴板。

在流水线中查看测试结果

在流水线详情中查看所有测试套件和用例。

要查看流水线测试结果:

  1. 转到您的流水线详情页面。
  2. 选择 Tests 标签页。
  3. 选择任何测试套件以查看单个测试用例。

测试结果显示 1671 个测试,总执行时间为 1 分 11 秒,以及各个作业的执行时间。

您也可以使用 Pipelines API 检索测试报告。

测试时间指标

测试结果显示不同的时间指标:

流水线持续时间
从流水线开始到完成所经过的时间。
测试执行时间
在所有作业中运行所有测试所花费的总时间。
排队时间
作业等待可用 runner 所花费的时间。

当作业并行运行时,累积的测试执行时间可能会超过流水线持续时间。 流水线持续时间显示您等待结果的时间,而测试执行时间显示使用的计算资源。

例如,如果许多测试作业在多个 runner 上并行运行,一个在 81 分钟内完成的流水线可能会显示 9 小时 10 分钟的测试执行时间。

将屏幕截图添加到测试报告

将屏幕截图添加到测试报告以帮助调试测试失败。

要将屏幕截图添加到测试报告:

  1. 在您的 JUnit XML 文件中,添加带有相对于 $CI_PROJECT_DIR 的屏幕截图路径的附件标签:

    <testcase time="1.00" name="Test">
      <system-out>[[ATTACHMENT|/path/to/some/file]]</system-out>
    </testcase>
  2. 在您的 .gitlab-ci.yml 文件中,配置您的作业以将屏幕截图作为 artifacts 上传:

    • 指定您的屏幕截图文件的路径。
    • 可选。使用 artifacts:when: always 在测试失败时上传屏幕截图。

    例如:

    ruby:
      stage: test
      script:
        - bundle install
        - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml
        - # Your test framework should save screenshots to a directory
      artifacts:
        when: always
        paths:
          - rspec.xml
          - screenshots/
        reports:
          junit: rspec.xml
  3. 运行您的流水线。

当您在 Test summary 面板中选择失败测试的 View details 时,您可以在测试详情对话框中访问屏幕截图链接。

一个失败的单元测试报告,包含测试详情和屏幕截图附件

故障排除

测试报告显示为空

您可能会在合并请求中看到一个空的 Test summary 面板。

当出现以下情况时,会发生此问题:

  • 报告 artifacts 已过期。
  • JUnit 文件超出大小限制。

要解决此问题,请为报告 artifact 设置更长的 expire_in 值,或运行新的流水线以生成新报告。

如果 JUnit 文件超出大小限制,请确保:

  • 单个 JUnit 文件小于 30 MB。
  • 作业的所有 JUnit 文件的总大小小于 100 MB。

对自定义限制的支持已在 epic 16374 中提出。

测试结果缺失

您在报告中看到的测试结果可能比预期的少。

当您的 JUnit XML 文件中有重复的测试名称时,可能会发生这种情况。每个名称仅使用第一个测试,重复的测试将被忽略。

要解决此问题,请确保所有测试名称和类都是唯一的。

合并请求中没有出现测试报告

您在合并请求中可能根本看不到 Test summary 面板。

当目标分支没有用于比较的测试数据时,可能会发生此问题。

要解决此问题,请在您的目标分支上运行流水线以生成基线测试数据。

JUnit XML 解析错误

您可能会在流水线中的作业名称旁边看到解析错误指示器。

当 JUnit XML 文件包含格式错误或无效元素时,可能会发生这种情况。

要解决此问题:

  • 验证您的 JUnit XML 文件是否符合标准格式。
  • 检查所有 XML 元素是否已正确关闭。
  • 确保属性名称和值的格式正确。

对于 grouped jobs,仅显示该组的第一个解析错误。