從 VSTest 遷移到 Microsoft。測試平台(MTP)

在本文中,你將學習如何從 VSTest 遷移到 MTP。

本文重點介紹遷移步驟與論元映射。

如果你還需要選擇平台,可以先從 測試平台總覽開始。

如果您需要dotnet test模式的詳細行為,請參考測試dotnet test

如果你需要一份平台與擴充功能命令列選項的單一清單,請參考 MTP CLI 選項參考

小提示

若要透過 AI 編碼助理自動化整個倉庫的遷移,請安裝 dotnet-testdotnet-test-migration.NET Agent Skills 中的插件。 請要求 test-migration 代理程式偵測並遷移你的測試設定,或叫用 migrate-vstest-to-mtp 技能來進行這項特定遷移。 合併前先檢視已產生的變更。

選擇使用 MTP

遷移的第一步是選擇使用 MTP。

針對所有測試框架,在解決方案中的所有測試專案加入 <OutputType>Exe</OutputType>。 之後,請遵照特定架構的指導。

MSTest

MTP 自 3.2.0 起由 MSTest 支援。 不過,建議您更新至最新的可用 MSTest 版本。

若要選擇加入,請在<EnableMSTestRunner>true</EnableMSTestRunner>檔案的PropertyGroup標籤下新增Directory.Build.props

備註

使用 MSTest.Sdk 時,預設使用 MTP,除非 <UseVSTest>true</UseVSTest> 另有說明。

NUnit

MTP 自 5.0.0 起由 NUnit3TestAdapter 支援。

若要選擇加入,請在<EnableNUnitRunner>true</EnableNUnitRunner>檔案的PropertyGroup標籤下新增Directory.Build.props

xUnit.net

MTP 從 xunit.v3 開始支援。

若要選擇加入,請在<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>檔案的PropertyGroup標籤下新增Directory.Build.props

dotnet test

選擇啟用 .NET 9 SDK 與更早版本

在 .NET 9 SDK 及更早版本中,沒有對 MTP 的原生支援。 支援建置在 VSTest 基礎結構之上。 要使用它,請在<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>檔案中PropertyGroup下新增Directory.Build.props

這很重要

在此模式下執行 MTP 支援時,您需要使用 -- 以將原來的參數與新平台的參數 dotnet test 區分開來。 例如: dotnet test --no-build -- --list-tests

選擇加入 .NET 10 SDK 和更新版本

從 .NET 10 SDK 開始,提供對 MTP 的原生支援。 若要使用它,您必須指定測試執行器,如 Microsoft.Testing.Platformglobal.json所示:

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

這很重要

在此模式下,不再需要額外的 --。 將其限於轉送測試應用程式引數,以避免歧義。

更新 dotnet test 呼叫

dotnet test 命令列選項分為兩類:與建置相關的參數和與測試相關的參數。

組建相關的引數與測試平台無關,因此不需要針對新平台進行更新。 此處列出與組建相關的引數:

  • -a|--arch <ARCHITECTURE>
  • --artifacts-path <ARTIFACTS_DIR>
  • -c|--configuration <CONFIGURATION>
  • -f|--framework <FRAMEWORK>
  • -e|--environment <NAME="VALUE">
  • --interactive
  • --no-build
  • --nologo
  • --no-restore
  • -o|--output <OUTPUT_DIRECTORY>
  • --os <OS>
  • -r|--runtime <RUNTIME_IDENTIFIER>
  • -v|--verbosity <LEVEL>

雖然 --arch 仍是建置相關的選項,但它取代了 VSTest 透過 RunConfiguration.TargetPlatform選擇的架構。 先將 --arch 傳遞給 dotnet test 本身,再放在任何 -- 分隔符號之前。

例如,遷移這個 VSTest 專案指令:

dotnet test MyTests.csproj -c Debug -- RunConfiguration.TargetPlatform=x86 /Parallel

對於 .NET 10 SDK 及後續版本,請使用以下 MTP 指令:

dotnet test --project MyTests.csproj -c Debug --arch x86

x86 取代為 x64 以 x64 為目標。 MTP 預設會平行執行測試模組,所以 /Parallel 不需要更換。 若要限制模組層級的平行性,請使用 --max-parallel-test-modules <NUMBER>

這很重要

你不能將 --arch--runtime--os--solution 結合。 這些選項設定 RuntimeIdentifier 為全域 MSBuild 屬性,而解決方案建置不支援全域 RuntimeIdentifier. 若要跨架構測試解決方案,請分別呼叫每個測試專案,或在個別測試專案中設定 RuntimeIdentifier

例如,替換以下四個解決方案層級的 VSTest 指令:

dotnet test MySolution.sln -c Debug -- RunConfiguration.TargetPlatform=x86 /Parallel
dotnet test MySolution.sln -c Release -- RunConfiguration.TargetPlatform=x86 /Parallel
dotnet test MySolution.sln -c Debug -- RunConfiguration.TargetPlatform=x64 /Parallel
dotnet test MySolution.sln -c Release -- RunConfiguration.TargetPlatform=x64 /Parallel

對於 .NET 10 SDK 及更新版本,請使用專案層級矩陣:

$testProjects = @("tests/A.Tests/A.Tests.csproj", "tests/B.Tests/B.Tests.csproj")
$testRunFailed = $false
foreach ($configuration in "Debug", "Release") {
    foreach ($architecture in "x86", "x64") {
        foreach ($testProject in $testProjects) {
            dotnet test --project $testProject -c $configuration --arch $architecture
            if ($LASTEXITCODE -ne 0) {
                $testRunFailed = $true
            }
        }
    }
}
if ($testRunFailed) {
    throw "One or more test runs failed."
}

與測試相關的引數是 VSTest 特定的,因此需要轉換以符合新平台。 下表顯示 VSTest 引數與新平臺之間的對應:

VSTest 引數 新平台論點
--test-adapter-path <ADAPTER_PATH> 對MTP無關
--blame 對MTP無關
--blame-crash --crashdump (需要 損毀傾印擴充功能
--blame-crash-dump-type <DUMP_TYPE> --crashdump-type (需要 損毀傾印擴充功能
--blame-crash-collect-always 不支援
--blame-hang --hangdump (需要 Hang dump 外掛程式
--blame-hang-dump-type <DUMP_TYPE> --hangdump-type (需要 Hang dump 外掛程式
--blame-hang-timeout <TIMESPAN> --hangdump-timeout (需要 Hang dump 外掛程式
--collect <DATA_COLLECTOR_NAME> 取決於資料收集器
-d\|--diag <LOG_FILE> --diagnostic
--filter <EXPRESSION> 取決於所選的測試框架
-l\|--logger <LOGGER> 取決於記錄儀
--results-directory <RESULTS_DIR> --results-directory <RESULTS_DIR>
-s\|--settings <SETTINGS_FILE> 取決於所選的測試框架
-t\|--list-tests --list-tests
-- RunConfiguration.TargetPlatform=<ARCHITECTURE> --arch <ARCHITECTURE> 用於專案呼叫
/Parallel 不需要選擇。 MTP 預設會平行執行測試模組。
-- <RunSettings arguments> --test-parameterVSTestBridge提供)

--collect

--collect 是 VSTest 中任何資料收集器的一般擴充點。 MTP 的擴充性模型不同,且沒有一個集中式論證必須所有資料收集者使用。 透過 MTP,每個資料收集器都可以新增自己的命令列選項。 例如,透過 VSTest 執行 Microsoft CodeCoverage 可能類似下列內容:

dotnet test --collect "Code Coverage;Format=cobertura"

有了MTP,這變成:

dotnet test --coverage --coverage-output-format cobertura

這很重要

要使用 --coverage,每個目標測試應用程式必須直接參考 Microsoft.Testing.Extensions.CodeCoverage NuGet 套件,或透過包含該套件的測試 SDK 配置或設定檔。

這很重要

如前所述,在使用以 VSTest 為基礎的 MTP dotnet test 時,需要在傳遞給平台的參數之前加上額外的 --。 所以,這變成了 dotnet test -- --coverage --coverage-output-format cobertura

--filter

--filter 是以 VSTest 為基礎的篩選器。

即使運行 MTP,MSTest 和 NUnit 也支援相同的過濾格式。

xUnit.net,在 MTP 執行時不支援相同的濾波器格式。 您必須從以 VSTest 為基礎的篩選移轉至 xunit.v3 中的新篩選支援,這是使用下列命令列選項提供的。

xUnit.net 具體選項:

  • --filter-class
  • --filter-not-class
  • --filter-method
  • --filter-not-method
  • --filter-namespace
  • --filter-not-namespace
  • --filter-trait
  • --filter-not-trait
  • --filter-query

如需詳細資訊,請參閱 xUnit.net 的 Microsoft.Testing.Platform 檔xUnit.net 的查詢篩選語言

小提示

如果你的解決方案混合了使用不同過濾語法的測試框架(例如 MSTest 和 xUnit.net),你可以用 TestingPlatformCommandLineArguments MSBuild 屬性條件性路由框架特定的參數。 詳情請參見 混合測試框架或擴充解決方案

--logger

VSTest 中通常稱為「logger」的部分,在 MTP 中則稱為「reporter」。 在 MTP 中,日誌明確用於診斷。

類似於 --collect--logger 是 VSTest 中任何記錄器(或在 MTP 語境下,任何 報告生成器)的通用擴充點。 每個 MTP 報告器都可以自行新增命令列選項,因此沒有像 VSTest --logger那樣集中式的命令列選項。

非常常用的 VSTest 記錄器之一是 TRX 記錄器。 此記錄器通常以下列方式調用:

dotnet test --logger trx

使用 MTP 時,指令變為:

dotnet test --report-trx

這很重要

要使用 --report-trx,每個目標測試應用程式必須直接參考 Microsoft.Testing.Extensions.TrxReport NuGet 套件,或透過包含該套件的測試 SDK 配置或設定檔。

這很重要

如前所述,在使用以 VSTest 為基礎的 MTP dotnet test 時,需要在傳遞給平台的參數之前加上額外的 --。 所以,這變成了 dotnet test -- --report-trx

GitHub Actions 報告器的選項是針對套件而設,且不可互換:

報告器套件 MTP 選項
Microsoft.Testing.Extensions.GitHubActionsReport --report-gh
GitHubActionsTestLogger --report-github

測試應用程式只有在安裝並註冊該選項的套件時才會辨識該選項。 例如,如果您遷移 --logger GitHubActions 並保留 GitHubActionsTestLogger 套件,請取代 VSTest 命令:

dotnet test --logger GitHubActions

使用 .NET 10 SDK 及更新版本,請使用:

dotnet test --report-github

對於 .NET 9 SDK 及更早版本,請改用dotnet test -- --report-github

--settings

VSTest 可用 --settings 來指定測試回合的 RunSettings 檔案。 RunSettings 不被核心 MTP 支援,並被更現代的 testconfig.json 設定檔取代。 不過,MSTest 和 NUnit 在執行 MTP 時仍支援舊版 RunSettings,且 --settings 仍被支援。

vstest.console.exe

如果您直接使用 vstest.console.exe ,我們建議將其替換為命令 dotnet test

測試總管

使用 Visual Studio 或 Visual Studio Code 測試檔案總管時,可能需要啟用 MTP 支援。

Visual Studio

Visual Studio 測試檔案總管自 17.14 版本起支援 MTP。 如果您使用的是舊版,您可能需要將 Visual Studio 更新為最新版本。

Visual Studio Code

Visual Studio Code 搭配 C# DevKit 支援 MTP。

Azure DevOps

使用 Azure DevOps 任務時,可能需要更新管線以使用 MTP,視你使用的任務而定。

VSTest 工作

如果您在 Azure DevOps 中使用 VSTest 工作 ,您可以將它取代為 .NET Core 工作

.NET Core CLI 任務

  • 如果您已將自訂的 arguments 傳遞至工作,請遵循 dotnet test 移轉的相同指導方針。

  • 如果你使用 DotNetCoreCLI 任務,但未透過 global.json 檔案選擇啟用 .NET 10 SDK 及更高版本的原生 MTP 體驗,那麼你將需要設定該任務的 arguments 來正確指向過去所指向的結果目錄,以及所需的 TRX 報告。 例如:

    - task: DotNetCoreCLI@2
      displayName: Run unit tests
      inputs:
        command: 'test'
        arguments: '-- --report-trx --results-directory $(Agent.TempDirectory)'
    

    本例中的測試應用程式必須註冊 Microsoft.Testing.Extensions.TrxReport。 直接新增套件,或使用包含套件的測試 SDK 設定或設定檔。

VSTest 與 MTP 的行為差異

執行零測試

如果測試組件完全沒執行測試,VSTest 會容忍並成功退出。 然而,MTP 失敗,並顯示退出代碼 8。 有多種方法可以繞過這個問題:

  • 執行測試時傳遞 --ignore-exit-code 8

  • 如果你想忽略特定測試專案的退出碼,可以在專案檔案中加入以下內容:

    <PropertyGroup>
      <TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --ignore-exit-code 8</TestingPlatformCommandLineArguments>
    </PropertyGroup>
    
  • 使用 TESTINGPLATFORM_EXITCODE_IGNORE 環境變數。

Console.InputEncoding 的保留

如果你在一個代碼頁明確更改過的主控台執行測試(例如在 Azure DevOps 中,代碼頁設為 65001,對應 UTF8),VSTest 和 MTP 的行為可能會不同。

  • 在使用 MTP 時,該編碼能夠一直被保留。
  • 當 VSTest 不以隔離模式(vstest.console 的預設行為)執行時,該編碼會被保留,類似於 MTP。
  • 當 VSTest 以隔離模式(預設行為 dotnet test)執行時,該編碼不會被保留在執行測試的 testhost 程序中。

小提示

VSTest 隔離模式不保留編碼的原因,是因為測試主機程序是以 CreateNoWindow = true開始的。 所以它沒有連接到原本的主機。

如果你有一個測試啟動另一個子程序並重定向其標準輸出,若以下條件全部適用,你可能會遇到問題:

  • 主控台代碼頁設定為 65001(UTF8)。 這種情況在人工耳蝸上可能有,但一般不會在本地發生。 要達到類似 CI 的局部行為,先執行 chcp 65001 測試。
  • 子程序以非 UTF8 編碼開始。 如果您自己的測試也設定了 CreateNoWindow = true,這種情況也可能發生。

這尤其棘手的是,子程序不預期會看到 UTF8 BOM(Byte-Order-Mark)位元組,而在 .NET Framework 的前述情境中可能會看到。

由於這種行為差異可能特別針對 BOM 位元組造成問題,一個變通方法是在組合語言初始化時將 InputEncoding 設定為 UTF8,但不含 BOM:

Console.InputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);

另一種解決方法是不使用 CreateNoWindow = true 來進行標準輸入重定向的子程序。