Microsoft.Testing.Platform

深入解析 Microsoft.Testing.Platform (MTP) 報告機制:從建置失敗到快速定位根因

作者

此內容提供了一套極具實務價值的 MTP 報告遷移指南,將複雜的底層測試平台功能轉化為可落地的工程決策路徑。其評價為『優秀』,理由在於它不只羅列功能,更明確區分了不同 CI 平台的支援差異(如 AzDO 與 GH Actions 的功能落差)以及版本相容性風險。唯一保留條件在於,由於 MTP 仍處於快速迭代期,部分 Preview 功能的穩定性需由使用者在實際環境中驗證。

深入解析 Microsoft.Testing.Platform (MTP) 報告機制:從建置失敗到快速定位根因

對於許多 Junior 工程師來說,在 CI(持續整合)環境中看到「Build Red」(建置失敗)往往是壓力來源。然而,單純知道「測試失敗」是不夠的。真正關鍵的問題在於:這次失敗是由目前的程式碼變更引起的嗎?這個測試以前是否也失敗過?我該去哪裡找證據?

如果答案需要你翻閱數千行的 Job Log、下載巨大的 Artifact 檔案,甚至得詢問記憶力好的資深同事,那麼這套報告機制就失效了。為了縮短從「發現失敗」到「做出決策」的路徑,微軟推出了 Microsoft.Testing.Platform (MTP) 的新一代報告功能。

什麼是 Microsoft.Testing.Platform (MTP)?

Microsoft.Testing.Platform (MTP) 是一個底層的測試執行平台,它驅動了我們常用的 dotnet test 命令、Visual Studio 與 VS Code 中的 Test Explorer,以及 CI 環境中的測試執行。

MTP 的設計目標是提供一個框架無關(Framework-agnostic)的執行層。無論你使用的是 MSTest、NUnit、xUnit.net、TUnit 還是 Expecto,只要這些框架支援 MTP,都能享受到本文提到的報告增強功能。

> 版本要求: 大部分功能需要 MTP 2.3.0 或更高版本。

---

核心技術與功能分析

MTP 的報告機制主要圍繞在三個維度:可見性 (Visibility)、上下文 (Context) 與 可靠性 (Reliability)。

將失敗資訊「內嵌」於工作流 (Inline Reporting) 傳統的測試報告通常被儲存在 Artifacts 中,開發者必須手動下載才能查看。MTP 現在支援將結果直接輸出為 CI 平台原生理解的格式:

GitHub Actions (--report-gh):失敗的測試會直接在程式碼對應的行數產生 Annotation (註釋)。跳過的測試會顯示為警告,且每個 Assembly 的日誌會被摺疊成獨立的群組,並在 Workflow 頁面直接生成摘要。 Azure DevOps (--report-azdo):同樣提供內嵌註釋與日誌分組。此外,透過 --publish-azdo-test-results,測試結果可以在執行過程中即時串流 (Live Stream) 到 Tests 標籤頁,而不需要等待整個 Job 完成後才執行 Publish 步驟。

利用歷史數據區分 Flaky 與 Regression 在大型測試套件中,最令人頭痛的是 Flaky Test (不穩定測試)——即同一段程式碼在沒有變更的情況下,有時通過、有時失敗。這會導致開發者對「紅燈」產生免疫力,將真正的 Regression (回歸錯誤) 誤認為是 Flaky。

目前 MTP 在 Azure DevOps 上提供了強大的歷史分析能力: 歷史註釋 (--report-azdo-flaky-history <days>):MTP 會查詢過去 N 天的 Pipeline 歷史。如果一個測試頻繁失敗,它會標記為 [flaky: failed 3/20 in last 14d];如果該測試之前一直通過,現在突然失敗,則標記為 [REGRESSION]。 自動降級 (--report-azdo-demote-known-flaky):可以將已知的不穩定測試從「錯誤 (Error)」降級為「警告 (Warning)」,使 CI 僅在發生真正的回歸錯誤時才阻斷 Merge。 動態慢速測試檢測 (--report-azdo-slow-test-history):不再使用單一的固定閾值,而是將每個測試與其自身的歷史執行時間對比,識別出異常變慢的測試。

崩潰恢復機制 (Crash-Resilient Reports) 最令人沮喪的情況是:測試執行過程中發生了硬崩潰 (Hard Crash),導致最終的報告檔案完全沒有生成,開發者完全不知道是哪個測試導致了崩潰。

MTP 引入了串流輸出 (Streaming) 機制: TRX 串流:測試結果在產生時即時寫入磁碟,而非在結束時一次性序列化。 崩潰轉儲 (--report-trx --crashdump):透過一個控制器進程監控測試主機。如果主機崩潰,控制器會將已完成的測試封裝成有效的 TRX 檔案,並在控制台明確列出崩潰時正在執行的測試名稱(例如:The following tests were still running when the test host crashed: [00:00:00] D_crash_the_host)。

---

實務應用與工程判斷

多格式輸出選擇 MTP 允許單次執行同時輸出多種格式,無需再寫額外的轉換腳本:

格式 開啟參數 適用對象 狀態 :--- :--- :--- :--- TRX --report-trx .NET 工具鏈、IDE Stable HTML --report-html 人員直接審查 Stable JUnit --report-junit 跨語言儀表板、通用 CI Preview CTRF --report-ctrf 多語言聚合分析 (JSON) Preview

建議做法: 如果下游有自動化工具讀取,選擇 TRX 或 JUnit;如果需要給人看,請加上 HTML 或 CTRF。

自動化與 LLM 友好的輸出 為了讓腳本或 AI Agent (LLM) 能可靠地消費測試結果,MTP 提供了 --list-tests json。它會輸出一個具有版本控制的 JSON 結構,包含每個測試的 UID 與精確的源碼位置(檔案、行號),避免了以往依賴解析控制台文字 (Console Scraping) 的不穩定性。

---

實作指南與限制

如何在專案中部署? 建議不要將參數寫在開發者的 Shell 歷史紀錄中,而是納入版本控制:

使用 testconfig.json:在測試專案旁建立此檔案,將參數放入 commandLineOptions 區塊。 使用 Directory.Build.props (針對 MSTest.Sdk):在根目錄統一設定 MSBuild 屬性(例如 <EnableMicrosoftTestingExtensionsHtmlReport>true</EnableMicrosoftTestingExtensionsHtmlReport>),一次套用到所有測試專案。

限制與風險 平台限制:歷史分析功能(Flaky/Regression/Slow-test)目前僅支援 Azure DevOps,GitHub Actions 尚未提供。 權限要求:Azure DevOps 的歷史分析需要調用 REST API,因此必須在 Pipeline Step 中傳遞 SYSTEM_ACCESSTOKEN。 版本相容性:MTP 2.x 的報告擴展包要求對應的框架適配器版本(如 MSTest.TestAdapter 4.0.0+)。若版本不匹配,啟動時會拋出 MissingMethodException。 混合模式不支援:不支援在同一個 Solution 中混合使用 MTP 專案與舊版 VSTest 專案。

Azure DevOps 遷移建議 如果你正在使用舊的 PublishTestResults@2 任務,可以考慮替換為 MTP 的 --publish-azdo-test-results。 注意: 兩者是獨立的發布路徑。如果同時開啟,Azure DevOps 會為同一次建置創建兩個測試執行紀錄,請擇一使用。至於「代碼覆蓋率 (Code Coverage)」標籤,目前仍需保留原有的 PublishCodeCoverageResults@2 任務。

最後的工程判斷

MTP 的演進方向非常明確:從「產生一個結果檔案」轉向「協助團隊做出決策」。

對於工程團隊而言,最優先的實作順序應為: 開啟內嵌報告 (--report-gh / --report-azdo) $\rightarrow$ 減少翻閱 Log 的時間。 導入歷史分析 (僅限 AzDO) $\rightarrow$ 降低對 Flaky Test 的噪音耐受度,快速識別 Regression。 配置 testconfig.json 或 Directory.Build.props $\rightarrow$ 確保開發環境與 CI 環境的報告行為一致。