migrate-vstest-to-mtp
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVSTest -> Microsoft.Testing.Platform Migration
从VSTest迁移至Microsoft.Testing.Platform
Migrate a .NET test solution from VSTest to Microsoft.Testing.Platform (MTP). The outcome is a solution where all test projects run on MTP, works correctly, and CI/CD pipelines are updated.
dotnet testImportant: Do not mix VSTest-based and MTP-based .NET test projects in the same solution or run configuration -- this is an unsupported scenario.
将.NET测试解决方案从VSTest迁移至Microsoft.Testing.Platform(简称MTP)。迁移完成后,解决方案中的所有测试项目均可在MTP上运行,命令可正常工作,且CI/CD流水线已完成更新。
dotnet test重要提示:请勿在同一解决方案或运行配置中混合使用基于VSTest和基于MTP的.NET测试项目——这属于不支持的场景。
When to Use
适用场景
- Switching from VSTest to Microsoft.Testing.Platform for any supported test framework
- Enabling /
dotnet run/ direct executable execution for test projectsdotnet watch - Enabling Native AOT or trimmed test execution
- Replacing with
vstest.console.exeon MTPdotnet test - Updating CI/CD pipelines from the VSTest task to the .NET Core CLI task
- Updating arguments from VSTest syntax to MTP syntax
dotnet test
- 为任意受支持的测试框架从VSTest切换至Microsoft.Testing.Platform
- 为测试项目启用/
dotnet run/ 直接执行可执行文件的功能dotnet watch - 启用Native AOT或裁剪后的测试执行
- 用基于MTP的替代
dotnet testvstest.console.exe - 将CI/CD流水线从VSTest任务更新为.NET Core CLI任务
- 将的参数从VSTest语法转换为MTP语法
dotnet test
When Not to Use
不适用场景
- The project already runs on Microsoft.Testing.Platform and there is no remaining MTP behavioral difference to resolve (e.g., exit code 8 for zero tests discovered)
- Migrating between test frameworks (e.g., MSTest to xUnit.net) -- different effort entirely
- The project builds UWP or packaged WinUI test projects -- MTP does not support these yet
- The solution mixes .NET and non-.NET test adapters (e.g., JavaScript or C++ adapters) -- VSTest is required
- Upgrading MSTest versions -- use or
migrate-mstest-v1v2-to-v3migrate-mstest-v3-to-v4
- 项目已在Microsoft.Testing.Platform上运行,且不存在需要解决的MTP行为差异(例如,未发现测试时返回退出代码8)
- 测试框架间迁移(如从MSTest迁移至xUnit.net)——这属于完全不同的工作内容
- 项目为UWP或打包的WinUI测试项目——MTP目前不支持这类项目
- 解决方案混合了.NET与非.NET测试适配器(如JavaScript或C++适配器)——必须使用VSTest
- MSTest版本升级——请使用或
migrate-mstest-v1v2-to-v3工具migrate-mstest-v3-to-v4
Inputs
输入项
| Input | Required | Description |
|---|---|---|
| Project or solution path | Yes | The |
| Test framework | No | MSTest, NUnit, xUnit.net v2, or xUnit.net v3. Auto-detected from package references |
| .NET SDK version | No | Determines |
| CI/CD pipeline files | No | Paths to pipeline definitions that invoke |
| 输入项 | 是否必填 | 描述 |
|---|---|---|
| 项目或解决方案路径 | 是 | 包含测试项目的 |
| 测试框架 | 否 | MSTest、NUnit、xUnit.net v2或xUnit.net v3。将从包引用中自动检测 |
| .NET SDK版本 | 否 | 决定 |
| CI/CD流水线文件 | 否 | 调用 |
Workflow
工作流程
Step 1: Assess the solution
步骤1:评估解决方案
- Identify the test framework for each test project -- see the skill for the package-to-framework mapping. Key indicators:
platform-detection- MSTest: References or
MSTest, or usesMSTest.TestAdapter(withMSTest.Sdknot set to<IsTestApplication>). Note:falsealone is a library dependency, not a test project.MSTest.TestFramework - NUnit: References
NUnit3TestAdapter - xUnit.net: References and
xunitxunit.runner.visualstudio
- MSTest: References
- Check the .NET SDK version () -- this determines how
dotnet --versionintegrates with MTPdotnet test - Check whether a file exists at the solution or repo root -- all MTP properties should go there for consistency
Directory.Build.props - Check for usage in CI scripts or pipeline definitions
vstest.console.exe - Check for VSTest-specific arguments in CI scripts:
dotnet test,--filter,--logger,--collect,--settings--blame* - Run to establish a baseline of test pass/fail counts
dotnet test
- 确定每个测试项目的测试框架——可参考工具中的包与框架映射关系。关键识别标志:
platform-detection- MSTest:引用了或
MSTest,或使用了MSTest.TestAdapter(且MSTest.Sdk未设置为<IsTestApplication>)。注意:仅引用false属于库依赖,并非测试项目。MSTest.TestFramework - NUnit:引用了
NUnit3TestAdapter - xUnit.net:引用了和
xunitxunit.runner.visualstudio
- MSTest:引用了
- 检查.NET SDK版本()——这将决定
dotnet --version与MTP的集成方式dotnet test - 检查解决方案或仓库根目录是否存在文件——所有MTP属性应统一配置在此文件中
Directory.Build.props - 检查CI脚本或流水线定义中是否使用了
vstest.console.exe - 检查CI脚本中是否存在VSTest专属的参数:
dotnet test、--filter、--logger、--collect、--settings--blame* - 运行以建立测试通过/失败数量的基准值
dotnet test
Step 2: Set up Directory.Build.props
步骤2:配置Directory.Build.props
Critical: Set MTP runner properties inat the solution or repo root whenever possible, rather than per-project. This prevents inconsistent configuration where some projects use VSTest and others use MTP (an unsupported scenario). Note: MTP also requires test projects to haveDirectory.Build.props. Only<OutputType>Exe</OutputType>sets this automatically. For all other setups (MSTest NuGet packages withMSTest.Sdk, NUnit withEnableMSTestRunner, xUnit.net withEnableNUnitRunner), prefer settingYTest.MTP.XUnit2centrally in<OutputType>Exe</OutputType>with a condition that targets only test projects. If you cannot reliably target only test projects fromDirectory.Build.props, settingDirectory.Build.propsper-project is an acceptable exception.<OutputType>Exe</OutputType>Conditioning in: Do NOT useDirectory.Build.props--Condition="'$(IsTestProject)' == 'true'"is set by the test SDK targets later in evaluation and is not available whenIsTestProjectis imported. Use a property that is available early, such asDirectory.Build.props, to target test projects by naming convention. For example, if all test projects end inMSBuildProjectName:.Testsxml<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))"> <OutputType>Exe</OutputType> </PropertyGroup>Adjust the condition (e.g.,,.EndsWith('Tests')) to match the test project naming convention used in the repository..Contains('.Test')
关键提示:尽可能在解决方案或仓库根目录的中设置MTP运行器属性,而非逐个项目配置。这可避免部分项目使用VSTest、部分使用MTP的不一致配置(属于不支持的场景)。 注意:MTP还要求测试项目设置Directory.Build.props。仅<OutputType>Exe</OutputType>会自动设置该属性。对于其他所有配置(使用MSTest.Sdk的MSTest NuGet包、使用EnableMSTestRunner的NUnit、使用EnableNUnitRunner的xUnit.net),建议在YTest.MTP.XUnit2中通过条件仅针对测试项目集中设置Directory.Build.props。如果无法通过<OutputType>Exe</OutputType>可靠地仅定位测试项目,则逐个项目设置Directory.Build.props是可接受的例外情况。<OutputType>Exe</OutputType>Directory.Build.props中的条件设置:请勿使用——Condition="'$(IsTestProject)' == 'true'"是在评估后期由测试SDK目标设置的,在导入IsTestProject时尚未可用。请使用早期可用的属性,例如Directory.Build.props,通过命名约定定位测试项目。例如,如果所有测试项目均以MSBuildProjectName结尾:.Testsxml<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))"> <OutputType>Exe</OutputType> </PropertyGroup>根据仓库中使用的测试项目命名约定调整条件(例如、.EndsWith('Tests'))。.Contains('.Test')
Step 3: Enable the framework-specific MTP runner
步骤3:启用特定框架的MTP运行器
Each framework has its own opt-in property. Add these in for consistency.
Directory.Build.props每个框架都有其专属的启用属性。为保持一致性,建议将这些属性添加到中。
Directory.Build.propsMSTest
MSTest
Option A -- MSTest NuGet packages (3.2.0+):
xml
<PropertyGroup>
<EnableMSTestRunner>true</EnableMSTestRunner>
<OutputType>Exe</OutputType>
</PropertyGroup>Ensure the project references MSTest 3.2.0 or later. If the version is already 3.2.0+, no MSTest version upgrade is needed for MTP migration.
Option B -- MSTest.Sdk:
When using , MTP is enabled by default -- no or property is needed (the SDK sets both automatically). The only action is: if the project has , remove it. That property forces the project to use VSTest instead of MTP.
MSTest.SdkEnableMSTestRunnerOutputType Exe<UseVSTest>true</UseVSTest>选项A——MSTest NuGet包(3.2.0及以上版本):
xml
<PropertyGroup>
<EnableMSTestRunner>true</EnableMSTestRunner>
<OutputType>Exe</OutputType>
</PropertyGroup>确保项目引用的MSTest版本为3.2.0或更高。如果版本已满足要求,则无需升级MSTest版本即可完成MTP迁移。
选项B——MSTest.Sdk:
使用时,MTP默认已启用——无需设置或属性(SDK会自动设置这两项)。仅需执行的操作是:如果项目中存在,请移除该配置。此属性会强制项目使用VSTest而非MTP。
MSTest.SdkEnableMSTestRunnerOutputType Exe<UseVSTest>true</UseVSTest>NUnit
NUnit
Requires 5.0.0 or later.
NUnit3TestAdapter- Update to 5.0.0+:
NUnit3TestAdapter
xml
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />- Enable the NUnit runner:
xml
<PropertyGroup>
<EnableNUnitRunner>true</EnableNUnitRunner>
<OutputType>Exe</OutputType>
</PropertyGroup>要求版本为5.0.0或更高。
NUnit3TestAdapter- 将更新至5.0.0及以上版本:
NUnit3TestAdapter
xml
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />- 启用NUnit运行器:
xml
<PropertyGroup>
<EnableNUnitRunner>true</EnableNUnitRunner>
<OutputType>Exe</OutputType>
</PropertyGroup>xUnit.net
xUnit.net
Add a reference to -- this package provides MTP support for xUnit.net v2 projects without requiring an upgrade to xunit.v3. You must also set to :
YTest.MTP.XUnit2OutputTypeExexml
<PackageReference Include="YTest.MTP.XUnit2" Version="0.4.0" />xml
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>Note:preserves the VSTestYTest.MTP.XUnit2syntax, so no filter migration is needed for xUnit.net v2. It also supports--filterfor runsettings (xunit-specific configurations only),--settings, TRX reporting viaxunit.runner.json, and--report-trx.--treenode-filter
添加对的引用——该包为xUnit.net v2项目提供MTP支持,无需升级至xunit.v3。同时必须将设置为:
YTest.MTP.XUnit2OutputTypeExexml
<PackageReference Include="YTest.MTP.XUnit2" Version="0.4.0" />xml
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>注意:保留了VSTest的YTest.MTP.XUnit2语法,因此xUnit.net v2无需进行过滤器迁移。它还支持--filter(仅针对xunit特定配置的runsettings)、--settings、通过xunit.runner.json生成TRX报告,以及--report-trx。--treenode-filter
xUnit.net v3
xUnit.net v3
xUnit.net v3 ( package) has built-in MTP support. Enable it with:
xunit.v3xml
<PropertyGroup>
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
</PropertyGroup>Important: xUnit.net v3 on MTP does NOT support the VSTestsyntax. You must translate filters to xUnit.net v3's native filter options (see Step 5).--filter
xUnit.net v3(包)原生支持MTP。通过以下配置启用:
xunit.v3xml
<PropertyGroup>
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
</PropertyGroup>重要提示:在MTP上运行的xUnit.net v3不支持VSTest的语法。必须将过滤器转换为xUnit.net v3的原生过滤选项(请参阅步骤5)。--filter
Step 4: Configure dotnet test integration
步骤4:配置dotnet test集成
The integration depends on the .NET SDK version.
dotnet testdotnet test.NET 10 SDK and later (recommended)
.NET 10 SDK及以上版本(推荐)
Use the native MTP mode by adding a section to :
testglobal.jsonjson
{
"sdk": {
"version": "10.0.100"
},
"test": {
"runner": "Microsoft.Testing.Platform"
}
}In this mode, arguments are passed directly -- for example, .
dotnet testdotnet test --report-trxImportant:does not support trailing commas. Ensure the JSON is strictly valid.global.json
通过在中添加部分使用原生MTP模式:
global.jsontestjson
{
"sdk": {
"version": "10.0.100"
},
"test": {
"runner": "Microsoft.Testing.Platform"
}
}在此模式下,的参数会直接传递——例如。
dotnet testdotnet test --report-trx重要提示:不支持尾随逗号。请确保JSON格式严格有效。global.json
.NET 9 SDK and earlier
.NET 9 SDK及更早版本
Use the VSTest mode of command to run MTP test projects by adding this property in :
dotnet testDirectory.Build.propsxml
<PropertyGroup>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
</PropertyGroup>Important: In this mode, you must useto separate--build arguments from MTP arguments. For example:dotnet test.dotnet test --no-build -- --list-tests
通过在中添加以下属性,使用命令的VSTest模式运行MTP测试项目:
Directory.Build.propsdotnet testxml
<PropertyGroup>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
</PropertyGroup>重要提示:在此模式下,必须使用分隔--的构建参数与MTP参数。例如:dotnet test。dotnet test --no-build -- --list-tests
Step 5: Update dotnet test command-line arguments
步骤5:更新dotnet test命令行参数
VSTest-specific arguments must be translated to MTP equivalents. Build-related arguments (, , , , , etc.) are unchanged.
-c-f--no-build--nologo-v| VSTest argument | MTP equivalent | Notes |
|---|---|---|
| Not applicable | MTP does not use external adapter discovery |
| Not applicable | |
| | Requires |
| | Requires CrashDump extension |
| | Requires |
| | Requires HangDump extension |
| | Requires HangDump extension |
| | Per-extension arguments |
| | |
| | Same syntax for MSTest, NUnit, and xUnit.net v2 (with |
| | Requires |
| | Same |
| | MSTest and NUnit still support |
| | Same |
| | Applicable only to MSTest and NUnit |
VSTest专属的参数必须转换为MTP等效参数。构建相关参数(、、、、等)保持不变。
-c-f--no-build--nologo-v| VSTest参数 | MTP等效参数 | 说明 |
|---|---|---|
| 不适用 | MTP不使用外部适配器发现机制 |
| 不适用 | |
| | 需要 |
| | 需要CrashDump扩展包 |
| | 需要 |
| | 需要HangDump扩展包 |
| | 需要HangDump扩展包 |
| | 扩展包专属参数 |
| | |
| | MSTest、NUnit和xUnit.net v2(使用 |
| | 需要 |
| | 保持一致 |
| | MSTest和NUnit仍支持 |
| | 保持一致 |
| | 仅适用于MSTest和NUnit |
Filter migration
过滤器迁移
MSTest, NUnit, and xUnit.net v2 (with ): The VSTest syntax is identical on both VSTest and MTP. No changes needed.
YTest.MTP.XUnit2--filterxUnit.net v3 (native MTP): xUnit.net v3 does NOT support the VSTest syntax on MTP. You must translate filters to xUnit.net v3's native filter options.
--filterMSTest、NUnit和xUnit.net v2(使用):VSTest的语法在VSTest和MTP上完全一致,无需修改。
YTest.MTP.XUnit2--filterxUnit.net v3(原生MTP):在MTP上运行的xUnit.net v3不支持VSTest的语法。必须将过滤器转换为xUnit.net v3的原生过滤选项。
--filterxUnit.net v3 filter flags
xUnit.net v3过滤标志
| Flag | Description |
|---|---|
| Run all tests in a given class. Supports wildcards ( |
| Exclude all tests in a given class |
| Run a specific test method |
| Exclude a specific test method |
| Run all tests in a namespace |
| Exclude all tests in a namespace |
| Run tests with a matching trait |
| Exclude tests with a matching trait |
Multiple values can be specified with a single flag: .
--filter-class Foo Bar| 标志 | 描述 |
|---|---|
| 运行指定类中的所有测试。支持通配符( |
| 排除指定类中的所有测试 |
| 运行特定测试方法 |
| 排除特定测试方法 |
| 运行指定命名空间中的所有测试 |
| 排除指定命名空间中的所有测试 |
| 运行具有匹配特性的测试 |
| 排除具有匹配特性的测试 |
单个标志可指定多个值:。
--filter-class Foo BarVSTest → xUnit.net v3 filter translation table
VSTest → xUnit.net v3过滤器转换对照表
VSTest | xUnit.net v3 MTP equivalent | Notes |
|---|---|---|
| | Wildcards required for substring match |
| | Exact match on fully qualified method |
| | Wildcards for substring match |
| | Filter by trait name/value pair |
| Complex expressions | | Uses xUnit.net query filter language (see below) |
VSTest | xUnit.net v3 MTP等效语法 | 说明 |
|---|---|---|
| | 子字符串匹配需要使用通配符 |
| | 完全匹配全限定方法名 |
| | 子字符串匹配需要使用通配符 |
| | 按特性名称/值对过滤 |
| 复杂表达式 | | 使用xUnit.net查询过滤语言(请参阅下文) |
xUnit.net v3 query filter language
xUnit.net v3查询过滤语言
For complex expressions, use with a path-segment syntax:
--filter-querytext
/<assemblyFilter>/<namespaceFilter>/<classFilter>/<methodFilter>[traitName=traitValue]Each segment matches against: assembly name, namespace, class name, method name. Use for "match all" in any segment. Documentation: https://xunit.net/docs/query-filter-language
*对于复杂表达式,请使用并采用路径段语法:
--filter-querytext
/<assemblyFilter>/<namespaceFilter>/<classFilter>/<methodFilter>[traitName=traitValue]每个段分别匹配:程序集名称、命名空间、类名、方法名。任意段均可使用表示“匹配全部”。文档链接:https://xunit.net/docs/query-filter-language
*Translation example
转换示例
shell
undefinedshell
undefinedVSTest
VSTest
dotnet test --filter "FullyQualifiedName~IntegrationTests&Category=Smoke"
dotnet test --filter "FullyQualifiedName~IntegrationTests&Category=Smoke"
xUnit.net v3 MTP -- using individual filters (AND behavior)
xUnit.net v3 MTP -- 使用独立过滤器(逻辑与行为)
dotnet test -- --filter-class IntegrationTests --filter-trait "Category=Smoke"
dotnet test -- --filter-class IntegrationTests --filter-trait "Category=Smoke"
xUnit.net v3 MTP -- using query language (assembly/namespace/class/method[trait])
xUnit.net v3 MTP -- 使用查询语言(程序集/命名空间/类/方法[特性])
dotnet test -- --filter-query "///IntegrationTests/*[Category=Smoke]"
> **Note**: When combining `--filter-class` and `--filter-trait`, both conditions must match (AND behavior). For complex expressions, use `--filter-query` with the path-segment syntax. See the [xUnit.net query filter language docs](https://xunit.net/docs/query-filter-language) for full reference.dotnet test -- --filter-query "///IntegrationTests/*[Category=Smoke]"
> **注意**:组合使用`--filter-class`和`--filter-trait`时,两个条件必须同时满足(逻辑与)。对于复杂表达式,请使用带路径段语法的`--filter-query`。完整参考请查看[xUnit.net查询过滤语言文档](https://xunit.net/docs/query-filter-language)。Step 6: Install MTP extension packages (if needed)
步骤6:安装MTP扩展包(如有需要)
If CI scripts use TRX reporting, crash dumps, or hang dumps, add the corresponding NuGet packages:
xml
<!-- TRX report generation (replaces --logger trx) -->
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" Version="1.6.2" />
<!-- Crash dump collection (replaces --blame-crash) -->
<PackageReference Include="Microsoft.Testing.Extensions.CrashDump" Version="1.6.2" />
<!-- Hang dump collection (replaces --blame-hang) -->
<PackageReference Include="Microsoft.Testing.Extensions.HangDump" Version="1.6.2" />
<!-- Code coverage (replaces --collect "Code Coverage") -->
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.13.0" />如果CI脚本使用TRX报告、崩溃转储或挂起转储,请添加对应的NuGet包:
xml
<!-- TRX报告生成(替代--logger trx) -->
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" Version="1.6.2" />
<!-- 崩溃转储收集(替代--blame-crash) -->
<PackageReference Include="Microsoft.Testing.Extensions.CrashDump" Version="1.6.2" />
<!-- 挂起转储收集(替代--blame-hang) -->
<PackageReference Include="Microsoft.Testing.Extensions.HangDump" Version="1.6.2" />
<!-- 代码覆盖率(替代--collect "Code Coverage") -->
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.13.0" />Step 7: Update CI/CD pipelines
步骤7:更新CI/CD流水线
Azure DevOps
Azure DevOps
If using the VSTest task (): Replace with the .NET Core CLI task ():
VSTest@3DotNetCoreCLI@2yaml
undefined如果使用VSTest任务():替换为.NET Core CLI任务():
VSTest@3DotNetCoreCLI@2yaml
undefinedBefore (VSTest task)
之前(VSTest任务)
- task: VSTest@3 inputs: testAssemblyVer2: '**/*Tests.dll' runSettingsFile: 'test.runsettings'
- task: VSTest@3 inputs: testAssemblyVer2: '**/*Tests.dll' runSettingsFile: 'test.runsettings'
After (.NET Core CLI task)
之后(.NET Core CLI任务)
- task: DotNetCoreCLI@2 displayName: Run tests inputs: command: 'test' arguments: '--no-build --configuration Release'
**If already using DotNetCoreCLI@2**: Update arguments per Step 5 translations. Remember the `--` separator on .NET 9 and earlier:
```yaml
- task: DotNetCoreCLI@2
displayName: Run tests
inputs:
command: 'test'
arguments: '--no-build -- --report-trx --results-directory $(Agent.TempDirectory)'- task: DotNetCoreCLI@2 displayName: Run tests inputs: command: 'test' arguments: '--no-build --configuration Release'
**如果已在使用DotNetCoreCLI@2**:根据步骤5的转换规则更新参数。注意在.NET 9及更早版本中需要使用`--`分隔符:
```yaml
- task: DotNetCoreCLI@2
displayName: Run tests
inputs:
command: 'test'
arguments: '--no-build -- --report-trx --results-directory $(Agent.TempDirectory)'GitHub Actions
GitHub Actions
Update invocations in workflow files with the same argument translations from Step 5.
dotnet test按照步骤5的参数转换规则,更新工作流文件中的调用。
dotnet testReplace vstest.console.exe
替换vstest.console.exe
If any script invokes directly, replace it with . The test projects are now executables and can also be run directly.
vstest.console.exedotnet test如果任何脚本直接调用,请替换为。测试项目现在已是可执行文件,也可直接运行。
vstest.console.exedotnet testStep 8: Handle behavioral differences
步骤8:处理行为差异
Zero tests exit code
无测试时的退出代码
VSTest silently succeeds when zero tests are discovered. MTP fails with exit code 8. Options:
- Pass when running tests
--ignore-exit-code 8 - Add to :
Directory.Build.props
xml
<PropertyGroup>
<TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --ignore-exit-code 8</TestingPlatformCommandLineArguments>
</PropertyGroup>- Use environment variable:
TESTINGPLATFORM_EXITCODE_IGNORE=8
VSTest在未发现任何测试时会静默成功。而MTP会返回退出代码8并失败。解决选项:
- 运行测试时传递参数
--ignore-exit-code 8 - 在中添加:
Directory.Build.props
xml
<PropertyGroup>
<TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --ignore-exit-code 8</TestingPlatformCommandLineArguments>
</PropertyGroup>- 使用环境变量:
TESTINGPLATFORM_EXITCODE_IGNORE=8
Step 9: Remove VSTest-only packages (optional)
步骤9:移除仅适用于VSTest的包(可选)
Once migration is complete and verified, remove packages that are only needed for VSTest:
- -- not needed for MTP (MSTest.Sdk v4 already omits it by default)
Microsoft.NET.Test.Sdk - -- only needed for VSTest discovery of xUnit.net (not needed when using
xunit.runner.visualstudio)YTest.MTP.XUnit2 - VSTest-only features -- the adapter is still needed but only for the MTP runner
NUnit3TestAdapter
Note: If you need to maintain VSTest compatibility during a transition period, keep these packages.
迁移完成并验证通过后,可移除仅用于VSTest的包:
- ——MTP无需此包(MSTest.Sdk v4默认已不再包含它)
Microsoft.NET.Test.Sdk - ——仅在VSTest发现xUnit.net测试时需要(使用
xunit.runner.visualstudio时无需此包)YTest.MTP.XUnit2 - 的VSTest专属功能——仍需保留适配器,但仅用于MTP运行器
NUnit3TestAdapter
注意:如果在过渡期间需要保持VSTest兼容性,请保留这些包。
Step 10: Verify
步骤10:验证
- Run -- confirm zero errors
dotnet build - Run -- confirm all tests pass
dotnet test - Compare test pass/fail counts to the pre-migration baseline
- Run the test executable directly (e.g., ) -- confirm it works
./bin/Debug/net8.0/MyTests.exe - Verify CI pipeline produces the expected test result artifacts (TRX files, code coverage, crash dumps)
- Test that Test Explorer in Visual Studio (17.14+) or VS Code discovers and runs tests
- 运行——确认无错误
dotnet build - 运行——确认所有测试通过
dotnet test - 将测试通过/失败数量与迁移前的基准值对比
- 直接运行测试可执行文件(例如)——确认可正常工作
./bin/Debug/net8.0/MyTests.exe - 验证CI流水线生成了预期的测试结果工件(TRX文件、代码覆盖率、崩溃转储)
- 测试Visual Studio(17.14及以上版本)或VS Code中的测试资源管理器是否可发现并运行测试
Validation
验证清单
- All test projects use MTP runner (no VSTest-only configuration remains)
- completes with zero errors
dotnet build - passes all tests and test counts match pre-migration baseline
dotnet test - Test executable runs directly (e.g., )
./bin/Debug/net8.0/MyTests.exe - CI pipeline produces expected test result artifacts (TRX files, code coverage, crash dumps)
- Test Explorer in Visual Studio or VS Code discovers and runs tests
- No invocations remain in CI scripts
vstest.console.exe - is set for all non-MSTest.Sdk test projects
<OutputType>Exe</OutputType>
- 所有测试项目均使用MTP运行器(无仅适用于VSTest的配置残留)
- 执行完成且无错误
dotnet build - 通过所有测试,且测试数量与迁移前基准值一致
dotnet test - 测试可执行文件可直接运行(例如)
./bin/Debug/net8.0/MyTests.exe - CI流水线生成了预期的测试结果工件(TRX文件、代码覆盖率、崩溃转储)
- Visual Studio或VS Code中的测试资源管理器可发现并运行测试
- CI脚本中无调用残留
vstest.console.exe - 所有非MSTest.Sdk的测试项目均设置了
<OutputType>Exe</OutputType>
Common Pitfalls
常见陷阱
| Pitfall | Solution |
|---|---|
| Mixing VSTest and MTP projects in the same solution | Migrate all test projects together -- mixed mode is unsupported |
| Use |
| Exit code 8 on CI without failures | MTP fails when zero tests run; use |
| MSTest.Sdk v4 + vstest.console no longer works | MSTest.Sdk v4 no longer adds |
Missing | Required for all setups except MSTest.Sdk (which sets it automatically) |
Using | |
| 陷阱 | 解决方案 |
|---|---|
| 同一解决方案中混合VSTest和MTP项目 | 同时迁移所有测试项目——混合模式不受支持 |
.NET 9及更早版本中 | 使用 |
| CI中无失败但返回退出代码8 | MTP在无测试运行时会失败;使用 |
| MSTest.Sdk v4 + vstest.console无法正常工作 | MSTest.Sdk v4不再添加 |
缺少 | 除MSTest.Sdk(会自动设置)外,所有配置均需设置此属性 |
在 | |
Next Steps
后续步骤
- Use for running tests on the new MTP platform
run-tests - Use for iterative test fixing with hot reload on MTP
mtp-hot-reload
- 使用工具在新的MTP平台上运行测试
run-tests - 使用工具在MTP上通过热重载进行迭代式测试修复
mtp-hot-reload