Microsoft.Testing.PlatformのCI Report設定|–report-gh・–report-azdo実践手順

Microsoft.Testing.Platform(MTP)のCI Report設定で、.NETテストの失敗をCI画面へ直接表示するには、GitHub Actionsでは--report-gh、Azure DevOpsでは--report-azdodotnet testに追加します。Azure DevOpsの「Tests」タブへテスト結果を逐次公開したい場合は、別機能の--publish-azdo-test-resultsも必要です。つまり、失敗箇所の注釈表示テスト結果の公開は、目的を分けて設定するのがポイントです。(Microsoft for Developers)

これらの機能はMTP 2.3.0で大きく拡充されました。ただし、Previewの扱いには注意が必要です。2026年8月6日に公開された公式記事では、MTP 2.3.3を基準にGitHub Actions、JUnit、CTRFのReporterがPreviewと説明されていました。その後、2026年9月2日にMTP 2.4.0が公開され、GitHub Actions Reporterは通常のリリースラインへ移行しています。一方、JUnit ReporterとCTRF Reporterは、2026年9月3日時点でもExperimentalです。(GitHub)

この記事では、--report-gh--report-azdoの具体的な設定方法に加え、Azure DevOpsのライブ公開、Flaky判定、GitHub Actionsの履歴保存、既存タスクから移行するときの注意点まで解説します。

目次

Microsoft.Testing.PlatformのCI Report設定で分けるべき3つの機能

MTPのレポート機能は、次の3種類に分けて考えると混乱しません。

目的GitHub ActionsAzure DevOps主な表示先
CI画面へ失敗を注釈表示する--report-gh--report-azdoAnnotations、ジョブログ、サマリー
テスト結果を管理画面へ逐次公開するMTPの同等機能は未提供--publish-azdo-test-resultsAzure DevOpsのTestsタブ
レポートファイルを生成する--report-trx--report-junit--report-ctrfなど同左TestResultsフォルダー、Artifact、外部ツール

--report-gh--report-azdoは、CIサービスが解釈できるコマンドを出力し、失敗したテストを開発者が見つけやすい場所へ表示する機能です。これらを有効にしても、TRXやJUnit XMLが自動生成されるわけではありません。

特に間違えやすいのがAzure DevOpsです。--report-azdoだけでは、失敗がAzure Pipelinesのログや注釈に表示されるだけです。Testsタブへ結果を登録するには、--publish-azdo-test-resultsを追加します。この2つは独立しているため、どちらか片方だけでも利用できます。(Microsoft for Developers)

MTP 2.3.0と2.4.0の違い

新しくCI Reportを設定する場合は、MTP 2.3.0を最低ラインとしつつ、MTP 2.4.0以降で検証するのが現実的です。

機能MTP 2.3.xMTP 2.4.0実務上の判断
--report-ghPreview通常のリリースラインへ移行新規導入は2.4.0以降を優先
--report-azdo利用可能注釈やロググループの制御を追加2.3.xでも基本表示は可能
--publish-azdo-test-results利用可能ライブ公開に関する不具合を修正2.4.0以降で事前検証
Azure DevOpsのFlaky履歴利用可能利用可能Azure DevOpsの履歴を直接参照
GitHub Actionsのテスト履歴未提供ローカルJSONスナップショットを追加Artifactによる永続化が必要
JUnit ReporterPreviewExperimentalバージョン固定と出力検証が必要
CTRF ReporterPreviewExperimentalスキーマ変更を想定して導入

MTP 2.4.0では、GitHub Actions Reporterの安定化だけでなく、--publish-azdo-test-results利用時の終了処理エラーや、公開失敗が診断ログにしか出ない問題も修正されています。Azure DevOpsへのライブ公開を新たに採用する場合は、テストアダプターとの互換性を確認したうえで、2.4.0以降へそろえるのが安全です。(GitHub)

設定前にMicrosoft.Testing.Platformの実行環境を確認する

テストプロジェクトがMTPで動いているか確認する

--report-gh--report-azdoは、MTPの拡張機能です。VSTestだけで動いているプロジェクトにオプションを追加しても、期待した結果にはなりません。

.NET 10 SDKでは、global.jsonに次の設定を追加すると、dotnet testをMTPモードで実行できます。

{
  "test": {
    "runner": "Microsoft.Testing.Platform"
  }
}

.NET 8または.NET 9 SDKでは、通常のdotnet testはVSTestモードです。MTP固有のオプションは、追加の--より後ろへ記述します。

dotnet test -- --report-gh

.NET 10のMTPモードでは追加の--は必須ではありませんが、テストアプリケーションへ渡す引数を明確にするため、この記事の例では原則として残しています。

.NET 8/9でMTPを呼び出す場合は、TestingPlatformDotnetTestSupportも有効になっている必要があります。MSTest.Sdkは、このプロパティを既定で有効にします。(Microsoft Learn)

CI Reporterの拡張パッケージを登録する

--report-gh--report-azdoは、MTP本体だけでは認識されません。対象のテストアプリケーションが、それぞれの拡張パッケージを登録している必要があります。

MSTest.Sdk 4.3.0以降のDefaultプロファイルでは、Azure DevOps ReporterとGitHub Actions Reporterのパッケージ参照が含まれます。ただし、パッケージが含まれていてもReporterは自動的には動作しません。実行時に--report-ghまたは--report-azdoを指定します。(Microsoft Learn)

NUnit、xUnit.net、TUnitなどで直接パッケージを追加する場合は、利用するCIに応じて参照を追加します。以下はMTP 2.4.0にそろえる例です。

<ItemGroup>
  <!-- GitHub Actionsを利用する場合 -->
  <PackageReference
    Include="Microsoft.Testing.Extensions.GitHubActionsReport"
    Version="2.4.0" />

  <!-- Azure DevOpsを利用する場合 -->
  <PackageReference
    Include="Microsoft.Testing.Extensions.AzureDevOpsReport"
    Version="2.4.0" />
</ItemGroup>

両方のCIサービスを使わないのであれば、必要なパッケージだけを追加します。Reporterパッケージと、テストフレームワークが参照するMTPのメジャーバージョンが合っていないと、起動時エラーになる可能性があります。(NuGet)

登録状態は、テストプロジェクトのディレクトリで次のコマンドを実行して確認できます。

dotnet test -- --help

ヘルプに--report-ghまたは--report-azdoが出てこない場合は、拡張パッケージが登録されていません。ソリューション全体へオプションを渡す場合は、対象となるすべてのテストプロジェクトで拡張機能が認識される必要があります。1つでも未登録のプロジェクトがあると、未認識オプションとして終了コード5になることがあります。(Microsoft Learn)

GitHub Actionsで–report-ghを設定する

最小構成はdotnet testへオプションを追加するだけ

既存のGitHub Actionsワークフローに、次のテストステップを設定します。

- name: Run .NET tests
  run: dotnet test --configuration Release -- --report-gh

GitHub Actions上でGITHUB_ACTIONS=trueとなっており、テストプロジェクトにReporterが登録されていれば、次の情報がCI画面へ表示されます。

  • 失敗したテストのエラー注釈
  • スキップされたテストの警告
  • テストアセンブリごとのロググループ
  • Workflowのジョブサマリー
  • 一定時間を超えたテストのNotice

ソース位置を解決できた場合は、WorkflowのAnnotationsだけでなく、Pull Requestの「Files changed」にも注釈が表示されます。(Microsoft Learn)

なお、--report-gh--report-githubは別のオプションです。--report-githubは別パッケージであるGitHubActionsTestLoggerのオプションであり、--report-ghの別名ではありません。エラーになったときは、パッケージ名とオプション名の組み合わせを確認してください。(Microsoft Learn)

ジョブサマリーの量を調整する

テスト数が多いリポジトリでは、毎回詳細なサマリーを表示すると確認すべき情報が埋もれます。MTP 2.4.0以降では、失敗時だけサマリーを表示できます。

- name: Run .NET tests
  run: >
    dotnet test --configuration Release --
    --report-gh
    --report-gh-step-summary on-failure
    --report-gh-step-summary-sections test-results,slow-tests
    --report-gh-slow-test-threshold 2m

主な調整オプションは次のとおりです。

オプション用途
--report-gh-groups on|offアセンブリごとのロググループを切り替える
--report-gh-annotations on|off失敗・スキップの注釈を切り替える
--report-gh-step-summary on|off|on-failureジョブサマリーの出力条件を指定する
--report-gh-step-summary-sectionsテスト結果、遅いテスト、カバレッジなどの掲載範囲を指定する
--report-gh-slow-test-notices on|off遅いテストのNoticeを切り替える
--report-gh-slow-test-threshold 2m遅いテストと判断する時間を指定する

on-failure--report-gh-step-summary-sectionsはMTP 2.4.0で追加されたため、MTP 2.3.xへ指定すると未認識オプションになります。(Microsoft Learn)

Pull Requestのコード行へ注釈が付かない場合

テスト失敗自体はAnnotationsへ表示されるものの、Pull Requestのコード行へ注釈が付かないことがあります。

MTPは、最初に例外のスタックトレースからワークスペース内のファイルを探します。解決できない場合は、テストフレームワークが報告したテスト定義位置を利用します。どちらも取得できない場合、ファイルや行番号を持たないタイトルだけの注釈になります。(NuGet)

確認すべきポイントは次のとおりです。

  • テスト実行前にリポジトリをCheckoutしているか
  • 対象ソースがGITHUB_WORKSPACE配下に存在するか
  • ReleaseビルドでもPDBなどのデバッグシンボルを残しているか
  • ビルドしたDLLだけを別ディレクトリへ移して実行していないか
  • 使用しているテストアダプターがソース位置を報告できるか

行番号が取得できなくても、テスト名と失敗メッセージはWorkflowのAnnotationsで確認できます。

MTP 2.4.0以降でGitHub Actionsの履歴を保存する

MTP 2.4.0では、GitHub Actions Reporterに--report-gh-historyが追加されました。

- name: Run .NET tests with history
  run: >
    dotnet test --configuration Release --
    --report-gh
    --report-gh-history .test-history/history.json
    --report-gh-history-window 14

ただし、このコマンドだけでは履歴は次回のWorkflowへ引き継がれません。GitHub Actionsの実行環境は毎回作り直されるため、次の流れが必要です。

  1. テスト開始前に、既存の履歴JSONをArtifactから.test-historyへ復元する
  2. --report-gh-historyを付けてテストを実行する
  3. テスト成功・失敗にかかわらず、更新されたJSONをArtifactへ保存する
  4. Pull Requestでは読み取りだけを行い、既定ブランチの実行だけが履歴を更新する

GitHub Actions Reporterは、GitHubのテスト履歴APIへ直接問い合わせるのではなく、ローカルJSONスナップショットを読み書きします。Artifactの取得と保存はWorkflow側が担当するため、テストプロセスへGITHUB_TOKENを渡す必要はありません。(NuGet)

Azure DevOpsで–report-azdoを設定する

失敗をAzure Pipelinesの画面へ表示する

Azure DevOpsでは、テストコマンドに--report-azdoを追加します。

- script: >
    dotnet test --configuration Release --
    --report-azdo
    --report-azdo-summary
  displayName: Run .NET tests

--report-azdoは、Azure DevOpsが解釈できるLogging Commandとして失敗や警告を出力します。--report-azdo-summaryを追加すると、テスト終了時にMarkdown形式のジョブサマリーもアップロードされます。

MTP 2.4.0では、失敗・スキップの注釈を--report-azdo-annotations on|offで制御できます。また、--report-azdo-groups on|offでアセンブリごとのロググループを切り替えられます。(Microsoft Learn)

Testsタブへ結果を公開する

Azure DevOpsのTestsタブへ結果を登録する場合は、--publish-azdo-test-resultsを追加します。

- script: >
    dotnet test --configuration Release --
    --report-azdo
    --report-azdo-summary
    --publish-azdo-test-results
    --publish-azdo-run-name "Unit tests"
  displayName: Run and publish .NET tests
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)

--publish-azdo-test-resultsは、TRXファイルを後から読み込む方式ではありません。MTPが保持している結果をAzure DevOpsのREST APIへ送り、実行中からテスト結果を公開します。MTP 2.4.0では、作成したテストランのURLもログへ表示されるため、実行中の結果へ直接移動できます。(NuGet)

Azure DevOpsのAPIへ接続するため、ジョブアクセストークンをSYSTEM_ACCESSTOKENとしてテストプロセスへ渡します。トークンを渡しても、シークレット値そのものをコマンドライン引数へ書く必要はありません。(GitHub)

PublishTestResults@2との二重公開を避ける

--publish-azdo-test-resultsPublishTestResults@2を同時に有効にすると、Azure DevOps上に2つのテストランが作られます。

従来のパイプラインが次の構成になっている場合は、どちらか一方へ統一します。

- task: PublishTestResults@2

DotNetCoreCLI@2command: testを利用している場合も注意が必要です。publishTestResultsの既定値はtrueであり、TRXを生成して自動公開します。MTPのライブ公開へ切り替える場合は、次のように無効化します。(Microsoft Learn)

- task: DotNetCoreCLI@2
  displayName: Run and publish .NET tests
  inputs:
    command: test
    publishTestResults: false
    arguments: >-
      --configuration Release
      --
      --report-azdo
      --report-azdo-summary
      --publish-azdo-test-results
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)

置き換え関係は次のようになります。

従来のタスクMTPで置き換える機能
PublishTestResults@2--publish-azdo-test-results
PublishBuildArtifacts@1またはPublishPipelineArtifact@1--report-azdo-upload-artifacts files
PublishCodeCoverageResults@2置き換え不可

MTPのライブ公開でカバレッジファイルをテストランへ添付できても、Azure Pipelinesの「Code Coverage」タブへ集計結果を表示する処理とは別です。Code Coverageタブを利用している場合は、既存のPublishCodeCoverageResults@2を残してください。(Microsoft for Developers)

2.3系のライブ公開でエラーになる場合

--publish-azdo-test-resultsについては、MTP 2.3系でテスト結果の公開後にObjectDisposedExceptionが発生し、テストがすべて成功していてもプロセスが非ゼロ終了する問題が報告されていました。

MTP 2.4.0では、次の点が修正されています。

  • 終了処理でObjectDisposedExceptionが発生する問題
  • 公開処理の失敗が通常ログに表示されない問題
  • 再実行されたテスト結果を1つの論理結果として扱う処理
  • Retryの各試行を識別しやすくする表示

ライブ公開を導入する場合は、MTP本体、Azure DevOps Reporter、テストアダプターを一括して更新し、検証用ブランチで成功・失敗・Retryの各パターンを確認してください。(GitHub)

Azure DevOpsの履歴からFlakyとRegressionを判定する

Flakyテストとは、ソースコードの変更とは無関係に、同じテストが成功したり失敗したりする不安定なテストです。失敗のたびに「おそらくFlakyだろう」と判断していると、本物の不具合まで見逃しやすくなります。

Azure DevOpsでは、--report-azdo-flaky-historyを使うと、過去のテスト結果を参照して失敗へ履歴情報を追加できます。

- script: >
    dotnet test --configuration Release --
    --report-azdo
    --report-azdo-summary
    --report-azdo-flaky-history 14
  displayName: Run .NET tests with flaky history
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)

14は、過去14日間を調べる指定です。設定可能な範囲は1日から90日です。

過去にも断続的に失敗しているテストには、次のような履歴が付きます。

[flaky: failed 3/20 in last 14d]

指定した期間に失敗履歴がない場合は、新しく発生した問題として表示されます。

[REGRESSION]

履歴情報はAzure DevOpsのREST APIから取得するため、SYSTEM_ACCESSTOKENが必要です。トークンがない場合、テスト実行自体は継続しますが、履歴ベースの注釈はスキップされます。(Microsoft for Developers)

Flakyテストを自動的に警告へ下げる

次のオプションを追加すると、過去の履歴からFlakyと判断された失敗をエラーではなく警告として扱えます。

--report-azdo-demote-known-flaky

既定では、履歴期間内の失敗率が25%以上のテストが降格対象になります。ただし、導入直後から自動降格を有効にするのは避けた方が安全です。

まずは--report-azdo-flaky-historyだけを有効にし、履歴表示と実際の原因が一致しているかを確認します。その後、既知のFlakyテストだけを隔離する運用が固まってから、自動降格を検討してください。Microsoftのテストチームでも、履歴は判断材料として表示しつつ、自動降格を無効にする運用例が紹介されています。(Microsoft for Developers)

明示的に隔離するテストが決まっている場合は、--report-azdo-quarantine-fileでテスト名やパターンを記載したファイルを指定する方法もあります。

履歴ベースのFlaky判定はAzure DevOpsだけなのか

MTP 2.3.xを前提にすると、CIサービスの履歴を参照してFlakyとRegressionを区別できるのはAzure DevOpsだけでした。

MTP 2.4.0ではGitHub Actionsにも--report-gh-historyが追加されたため、「履歴機能は完全にAzure DevOps限定」という説明は現在では正確ではありません。ただし、両者の仕組みは大きく異なります。

比較項目Azure DevOpsGitHub Actions 2.4.0以降
履歴の取得元Azure DevOpsのテスト結果履歴ローカルJSONスナップショット
主なオプション--report-azdo-flaky-history 14--report-gh-history path
認証SYSTEM_ACCESSTOKENテストプロセスにはトークン不要
履歴の永続化Azure DevOps側Workflow Artifact側
新規失敗と過去失敗の判別Flaky/Regressionとして注釈過去の失敗コンテキストを表示
既知Flakyの警告降格--report-azdo-demote-known-flakyAzure DevOps相当のオプションなし

Azure DevOpsはサーバー側に蓄積されたテスト履歴を利用するため、既存のTestsタブとの連携が強みです。GitHub Actionsはリポジトリ側で履歴JSONの保存方法を管理でき、Pull Requestへ書き込み権限を与えずに履歴を参照できる点が特徴です。(NuGet)

Azure DevOpsのロググループを有効にするときの注意点

MTP 2.4.0では、Azure DevOpsでも次のオプションによりアセンブリ単位の折りたたみ表示を有効にできます。

--report-azdo-groups on

ただし、複数のテストアセンブリを並列実行している場合は、有効にしない方が安全です。Azure DevOpsのグループ開始・終了コマンドは順番に処理されるため、複数アセンブリの出力が混ざると、グループの対応関係が崩れることがあります。

安定版のMTP 2.4.0では、この問題を避けるため--report-azdo-groupsの既定値がoffになっています。onにするのは、単一アセンブリを実行する場合か、アセンブリを直列実行する場合に限定してください。(Microsoft Learn)

testconfig.jsonでCI Report設定を共通化する

毎回CIのYAMLへ長いオプションを書く代わりに、MTP 2.3.0以降ではtestconfig.jsoncommandLineOptionsへ設定を保存できます。

Azure DevOps向けの例は次のとおりです。

{
  "commandLineOptions": {
    "report-trx": true,
    "report-azdo": true,
    "report-azdo-flaky-history": 14
  }
}

テストプロジェクトと一緒にコミットしておけば、CIとローカルで同じ基本設定を利用できます。コマンドラインで指定した値は、設定ファイルの値より優先されます。

スペルを間違えた場合も、設定が黙って無視されるのではなく、該当する設定ファイルと未認識オプションがエラーに表示されます。(Microsoft for Developers)

ただし、testconfig.jsonは拡張パッケージをインストールしません。設定ファイルにreport-azdoと書いても、対象プロジェクトにAzure DevOps Reporterが登録されていなければ実行できません。

GitHub ActionsとAzure DevOpsの両方を使うリポジトリでは、次のように設定ファイルを分ける方法もあります。

testconfig.github.json
testconfig.azdo.json

CIから明示的に読み込む場合は、--config-fileを指定します。

dotnet test -- --config-file testconfig.github.json

プロバイダーごとに設定を分けておくと、Azure DevOps専用のFlaky履歴や、GitHub Actions専用のサマリー設定が混在しにくくなります。

JUnit・CTRF・TRX Reporterとの使い分け

--report-gh--report-azdoは、CI画面を見やすくする機能です。一方、TRX、JUnit、CTRFは、結果をファイルとして外部ツールへ渡すために使います。

形式オプション主な用途2026年9月3日時点の扱い
TRX--report-trx.NETツール、Azure DevOps、保存用Stable
JUnit XML--report-junitJenkins、GitLab、各種テスト集計ツールExperimental
CTRF JSON--report-ctrf複数言語の集約、ダッシュボード、AI連携Experimental

これらは排他的ではありません。GitHub Actionsの画面へ注釈を表示しながら、TRXも保存できます。

dotnet test -- --report-gh --report-trx

Azure DevOpsでも同様です。

dotnet test -- --report-azdo --report-trx

JUnit ReporterとCTRF Reporterは、現在もalpha版かつExperimentalと明記されています。CIの後段処理で利用する場合は、NuGetパッケージのバージョンを固定し、更新前にファイル構造や読み込み側ツールとの互換性を確認してください。(NuGet)

CI Reportが表示されないときの確認項目

症状主な原因対処
Unrecognized option '--report-gh'と出るReporterが未登録NuGet参照やMSTest.Sdkプロファイルを確認する
ソリューション実行で終了コード5になる一部プロジェクトだけReporterが未登録対象となる全テストプロジェクトへ拡張を登録する
ローカルでは--report-ghを付けても何も出ないGitHub Actions上ではないGITHUB_ACTIONS=trueのCI環境で確認する
--report-githubでは動くが--report-ghでは動かない別パッケージのオプションを混同しているパッケージ名とオプション名をそろえる
Azure DevOpsのTestsタブに結果が出ない--report-azdoしか指定していない--publish-azdo-test-resultsとトークンを追加する
Azure DevOpsにテストランが2つ作られるMTPと従来タスクが二重公開しているPublishTestResults@2またはpublishTestResultsを無効にする
Flaky履歴が表示されないSYSTEM_ACCESSTOKENが渡っていないステップのenvへ明示的に設定する
GitHubの注釈にファイル名や行番号がないPDBまたはソース位置を解決できないデバッグシンボルとワークスペース内のソースを確認する
.NET 8/9でオプションが無視される追加の--がないdotnet test -- --report-ghの形で実行する
Azure DevOpsのログが不自然に折りたたまれる並列実行中にグループを有効化している--report-azdo-groups offへ戻す

原因が分からない場合は、まず1つのテストプロジェクトだけを対象にして、次の順番で確認すると切り分けやすくなります。

  1. dotnet testだけでテストが動くか確認する
  2. dotnet test -- --helpでReporterのオプションを確認する
  3. --report-ghまたは--report-azdoだけを追加する
  4. 意図的に失敗するテストを1件作り、CI画面の注釈を確認する
  5. Azure DevOpsでは、その後に--publish-azdo-test-resultsを追加する
  6. 最後にFlaky履歴、Artifact、TRXなどを追加する

まとめ:まず注釈表示を有効にしてから機能を追加する

Microsoft.Testing.PlatformのCI Report設定では、最初からすべての機能を有効にする必要はありません。

GitHub Actionsでは、まず次の最小構成から始めます。

dotnet test -- --report-gh

Azure DevOpsでは、まず失敗の注釈表示を確認します。

dotnet test -- --report-azdo --report-azdo-summary

Testsタブへの公開が必要になった段階で、--publish-azdo-test-resultsを追加します。その際は、PublishTestResults@2DotNetCoreCLI@2の自動公開を無効にし、二重登録を避けます。

Flakyテストへの対応は、いきなり警告へ降格するのではなく、最初に14日程度の履歴を表示して実態を確認する方法が安全です。GitHub ActionsではArtifactで履歴JSONを保存し、Azure DevOpsではSYSTEM_ACCESSTOKENを使ってサービス側の履歴を参照します。

まず1つのテストプロジェクトへReporterを追加し、意図的に失敗させたテストが、ログを開かなくてもCI画面から確認できる状態を作ることが次の行動になります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次