Microsoft.Testing.Platform(MTP)のCI Report設定で、.NETテストの失敗をCI画面へ直接表示するには、GitHub Actionsでは--report-gh、Azure DevOpsでは--report-azdoをdotnet 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 Actions | Azure DevOps | 主な表示先 |
|---|---|---|---|
| CI画面へ失敗を注釈表示する | --report-gh | --report-azdo | Annotations、ジョブログ、サマリー |
| テスト結果を管理画面へ逐次公開する | MTPの同等機能は未提供 | --publish-azdo-test-results | Azure 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.x | MTP 2.4.0 | 実務上の判断 |
|---|---|---|---|
--report-gh | Preview | 通常のリリースラインへ移行 | 新規導入は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 Reporter | Preview | Experimental | バージョン固定と出力検証が必要 |
| CTRF Reporter | Preview | Experimental | スキーマ変更を想定して導入 |
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の実行環境は毎回作り直されるため、次の流れが必要です。
- テスト開始前に、既存の履歴JSONをArtifactから
.test-historyへ復元する --report-gh-historyを付けてテストを実行する- テスト成功・失敗にかかわらず、更新されたJSONをArtifactへ保存する
- 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-resultsとPublishTestResults@2を同時に有効にすると、Azure DevOps上に2つのテストランが作られます。
従来のパイプラインが次の構成になっている場合は、どちらか一方へ統一します。
- task: PublishTestResults@2
DotNetCoreCLI@2のcommand: 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 DevOps | GitHub 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-flaky | Azure 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.jsonのcommandLineOptionsへ設定を保存できます。
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-junit | Jenkins、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つのテストプロジェクトだけを対象にして、次の順番で確認すると切り分けやすくなります。
dotnet testだけでテストが動くか確認するdotnet test -- --helpでReporterのオプションを確認する--report-ghまたは--report-azdoだけを追加する- 意図的に失敗するテストを1件作り、CI画面の注釈を確認する
- Azure DevOpsでは、その後に
--publish-azdo-test-resultsを追加する - 最後に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@2やDotNetCoreCLI@2の自動公開を無効にし、二重登録を避けます。
Flakyテストへの対応は、いきなり警告へ降格するのではなく、最初に14日程度の履歴を表示して実態を確認する方法が安全です。GitHub ActionsではArtifactで履歴JSONを保存し、Azure DevOpsではSYSTEM_ACCESSTOKENを使ってサービス側の履歴を参照します。
まず1つのテストプロジェクトへReporterを追加し、意図的に失敗させたテストが、ログを開かなくてもCI画面から確認できる状態を作ることが次の行動になります。

コメント