JUnitテストレポート

GitLab 11.2で導入されました。GitLab Runner 11.2以降が必要です。

概要

CI/CDパイプラインにコードを検証するテストジョブが含まれていることは非常によくあることです。テストが失敗するとパイプラインが失敗したことがユーザーに通知されます。マージリクエストの作業をしている人はジョブのログをチェックし、どこでテストが失敗したかを確認して修正しなければなりません。

JUnitのテストレポートを使用するようにジョブを設定すると、GitLabのマージリクエストにレポートが表示されるので、ログ全体をチェックしなくても簡単かつ迅速に障害を特定できます。

マージリクエストを使用せずに、ジョブのログを検索せずにJUnitの出力を見たい場合は、パイプラインの詳細ビューでJUnitのテストレポートをすべて見ることができます。

ユースケース

次のようなワークフローを考えてみましょう。

  1. プロジェクトはGitLab CI/CDを使用していて、masterブランチは信頼でき、パイプラインは正常に動作していることを示しています。
  2. チームの誰かがマージリクエストを作成して、そのテストが失敗すると、パイプラインには赤いアイコンが表示されます。詳細を調べるには、ジョブのログを調べてテストが失敗した原因を突き止める必要があります。しかし、ログは何千行にもなる場合があります。
  3. JUnitのテストレポートを設定すると、GitLabのマージリクエストに収集されたテスト結果がすぐに表示されます。これにより、ジョブのログを検索する手間を削減できます。
  4. 開発とデバッグのワークフローがより簡単に、より速く、より効率的になります。

どのように動作するか

まず、GitLab Runnerは、すべてのJUnit XMLファイルをアーティファクトとしてGitLabにアップロードします。 次に、マージリクエストにアクセスすると、GitLabはheadブランチとベースブランチのJUnitテストレポートの比較を開始します。

  • ベースブランチとは、マージリクエストのターゲットブランチ(通常master)のことです。
  • headブランチとは、マージリクエストのソースブランチのことです。

レポートパネルには、失敗したテストの数、エラーの数、修正されたテストの数を示すサマリーがあります。ベースブランチのデータが利用できず比較ができない場合は、パネルにはheadブランチで失敗したテストのリストが表示されます。

表示される結果は4つに分類されます。

  1. 新しく失敗したテスト: ベースブランチでは成功し、headブランチでは失敗したテストケース
  2. 新たに発生したエラー: ベースブランチでは成功し、headブランチではエラーにより失敗したテストケース
  3. 元から発生していた失敗: ベースブランチとheadブランチの両方で失敗したテストケース
  4. 解決された失敗: ベースブランチで失敗し、headブランチで成功したテストケース

パネル内の各エントリには、上のリストからテスト名とそのタイプが表示されます。テスト名をクリックすると、実行時間とエラー出力の詳細が表示されるモーダルウィンドウが開きます。

Test Reports Widget

設定方法

Note: JUnitテストでサポートされている言語の一覧は、Wikipedia の記事を参照してください。

マージリクエストでJUnitのレポートを有効にするには、artifacts:reports:junit.gitlab-ci.ymlに追加し、生成されたテストレポートのパスを指定する必要があります。レポートはxmlファイルでなければなりません。そうしないとGitLabはエラー500を返します。

以下の例では、テストステージでジョブが実行され、GitLabが各ジョブからJUnitのテストレポートを収集します。 各ジョブが実行された後、XMLレポートはアーティファクトとしてGitLabに保存され、その結果がマージリクエストウィジェットに表示されます。

Note: JUnitの出力ファイルを参照したい場合は、artifacts:pathsキーワードを一緒に使用してください。その例をRubyの例として以下に示します。

Rubyの例

.gitlab-ci.ymlで以下のジョブを使用します。これにはartifacts:pathsキーワードが含まれており、JUnit出力ファイルへのリンクを提供します。

## Use https://github.com/sj26/rspec_junit_formatter to generate a JUnit report with rspec
ruby:
  stage: test
  script:
    - bundle install
    - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml
  artifacts:
    paths:
      - rspec.xml
    reports:
      junit: rspec.xml

Goの例

.gitlab-ci.ymlで次のようなジョブを使用し、-set-exit-codeを使用するようにします。

## Use https://github.com/jstemmer/go-junit-report to generate a JUnit report with go
golang:
  stage: test
  script:
    - go get -u github.com/jstemmer/go-junit-report
    - go test -v 2>&1 | go-junit-report -set-exit-code > report.xml
  artifacts:
    reports:
      junit: report.xml

Javaの例

Javaには、JUnitレポートを作成できるツールがいくつかあります。

Gradle

以下の例では、テスト・レポートの生成にgradleを使用しています。複数のテスト・タスクが定義されている場合、gradlebuild/test-results/の下に複数のディレクトリを生成します。この場合、パスbuild/test-results/test/**/TEST-*.xml.のようにglob形式でファイルパスを指定してください。

java:
  stage: test
  script:
    - gradle test
  artifacts:
    reports:
      junit: build/test-results/test/**/TEST-*.xml

Maven

SurefireおよびFailsafeのテストレポートを解析するには、.gitlab-ci.ymlで次のようなジョブを定義してください。

java:
  stage: test
  script:
    - mvn verify
  artifacts:
    reports:
      junit:
        - target/surefire-reports/TEST-*.xml
        - target/failsafe-reports/TEST-*.xml

Python example

以下の例では、pytestで--junitxml=report.xmlフラグを指定して、JUnitのフォーマットで出力しています。

pytest:
  stage: test
  script:
    - pytest --junitxml=report.xml
  artifacts:
    reports:
      junit: report.xml

C/C++の例

C/C++でJUnitレポートを作成できるツールがいくつかあります。

GoogleTest

異なるアーキテクチャ(x86x64arm)用に作成された複数のgtest実行ファイルがある場合は、そのファイル名を指定して各々テストを実行する必要があります。テスト結果は一緒に集計されます。

cpp:
  stage: test
  script:
    - gtest.exe --gtest_output="xml:report.xml"
  artifacts:
    reports:
      junit: report.xml

CUnit

CUnitは、CUnitCI.hマクロを使用して実行すると、自動的にJUnit XMLレポートを作成できます。

cunit:
  stage: test
  script:
    - ./my-cunit-test
  artifacts:
    reports:
      junit: ./my-cunit-test.xml

.NETの例

JunitXML.TestLoggerNuGetパッケージは、.Net Frameworkと.Net Coreアプリケーション用のテストレポートを生成できます。以下の例では、リポジトリのルートフォルダにソリューションがあり、サブフォルダに1つ以上のプロジェクトファイルがあることを想定しています。テストプロジェクトごとに1つの結果ファイルが生成され、各ファイルは新しいアーティファクトフォルダに配置されます。この例には、オプションの書式設定引数が含まれており、テストウィジェット内のテストデータの可読性を向上させます。完全な.Net Coreのサンプルが用意されています

## Source code and documentation are here: https://github.com/spekt/junit.testlogger/

Test:
  stage: test
  script:
    - 'dotnet test --test-adapter-path:. --logger:"junit;LogFilePath=..\artifacts\{assembly}-test-result.xml;MethodFormat=Class;FailureBodyFormat=Verbose"'
  artifacts:
    when: always
    paths:
      - ./**/*test-result.xml
    reports:
      junit:
        - ./**/*test-result.xml

GitLabでJUnitのテストレポートを表示する

  • GitLab 12.5で導入されました
  • フィーチャーフラグで有効・無効を切り替えることができ、デフォルトでは無効になっています。
  • GitLabのセルフマネージドインスタンスで使用するには、GitLabの管理者に有効にしてもらう必要があります。

JUnit XMLファイルを生成してパイプラインの一部としてアップロードした場合は、パイプラインの詳細ページでレポートを確認できます。このページのTestsタブには、XMLファイルから報告されたテストスイートとケースの一覧が表示されます。

Test Reports Widget

既知のすべてのテストスイートを表示し、それぞれをクリックすると、そのスイートを構成するケースを含む詳細を見ることができます。ケースはステータス順に表示され、失敗したケースが一番上に表示され、次にスキップされたケース、成功したケースが最後に表示されます。

また、GitLab API経由でレポートを取得できます。

JUnit テストレポート機能を有効にする

この機能はフィーチャーフラグ:junit_pipeline_viewで設定され、デフォルトでは無効になっています。この機能は、非常に大きなデータセットでのパフォーマンスの問題があるため、無効になっています。パフォーマンスが改善された場合、この機能はデフォルトで有効になります。

この機能を有効にするには、Railsのコンソールへのアクセス権を持つGitLab管理者に以下のコマンドを実行してもらいます。

Feature.enable(:junit_pipeline_view)

# Enable the feature for a specific project
Feature.enable(:junit_pipeline_view, Project.find(<your-project-id-here>))

GitLabでJUnitのスクリーンショットを表示する

  • GitLab 13.0から導入されました
  • フィーチャーフラグで有効・無効を切り替えることができ、デフォルトでは無効になっています。
  • GitLabのセルフマネージドインスタンスで使用するには、GitLabの管理者に有効にしてもらう必要があります。

JUnit XMLファイルにattachmentタグが含まれている場合は、GitLabが添付ファイルを解析します。

スクリーンショットをアーティファクトとしてGitLabにアップロードします。attachmentタグには、アップロードしたスクリーンショットの絶対パスを指定しなければなりません

<testcase time="1.00" name="Test">
  <system-out>[[ATTACHMENT|/absolute/path/to/some/file]]</system-out>
</testcase>

この課題が完了すると、添付ファイルがパイプラインの詳細ページに表示されます。

JUnitのスクリーンショット機能を有効にする

この機能はフィーチャーフラグ:junit_pipeline_screenshots_viewで設定され、デフォルトでは無効になっています。

この機能を有効にするには、Railsのコンソールへのアクセス権を持つGitLab管理者に以下のコマンドを実行してもらいます。

Feature.enable(:junit_pipeline_screenshots_view)