/migrate-vstest-to-mtp
Use this skill before answering, planning, or editing whenever .NET tests or CI are switching from VSTest to Microsoft.Testing.Platform (MTP), or an MTP migration behaves differently. Triggers include "switch from VSTest"; MSTest/NUnit/xUnit MTP enablement; OutputType=Exe only
Claude Code
$ npx -y skills add dotnet/skills --skill migrate-vstest-to-mtp --agent claude-code
Codex
$ npx skills add dotnet/skills --skill migrate-vstest-to-mtp -a codex -y
Cursor
$ npx skills add dotnet/skills --skill migrate-vstest-to-mtp -a cursor -y
Gemini CLI
$ npx skills add dotnet/skills --skill migrate-vstest-to-mtp -a gemini-cli -y
GitHub Copilot
$ npx skills add dotnet/skills --skill migrate-vstest-to-mtp -a github-copilot -y
OpenCode
$ npx skills add dotnet/skills --skill migrate-vstest-to-mtp -a opencode -y
Windsurf
$ npx skills add dotnet/skills --skill migrate-vstest-to-mtp -a windsurf -y
SKILL.md
migrate-vstest-to-mtp.SKILL.mdname: migrate-vstest-to-mtp
description: >
Use this skill before answering, planning, or editing whenever .NET tests or
CI are switching from VSTest to Microsoft.Testing.Platform (MTP), or an MTP
migration behaves differently. Triggers include "switch from VSTest";
MSTest/NUnit/xUnit MTP enablement; OutputType=Exe only for test projects in
Directory.Build.props; EnableMSTestRunner, EnableNUnitRunner,
UseMicrosoftTestingPlatformRunner, or YTest.MTP.XUnit2; .NET 10 global.json
test.runner and TestingPlatformDotnetTestSupport; translating VSTest
filters, logger, coverage, blame, or dump arguments; replacing VSTest@3;
and exit code 8 or zero tests. Also use for xUnit v3 MTP filters during a
v2-to-v3 upgrade. Do not use for framework conversion, TFM, UWP, or WinUI.
license: MIT
VSTest -> Microsoft.Testing.Platform Migration
Migrate a .NET test solution from VSTest to Microsoft.Testing.Platform (MTP). The outcome is a solution where all test projects run on MTP, `dotnet test` works correctly, and CI/CD pipelines are updated.
First Action
Inspect the supplied project, `Directory.Build.props`, `global.json`, and CI files before searching the web or answering from memory. Resolve the framework and SDK mode first: .NET 9 and earlier use the compatibility property plus the `--` separator; .NET 10 native MTP uses `global.json`, removes that property, and passes MTP arguments without the separator. For central properties, never condition on `IsTestProject` in `Directory.Build.props`; use a property already available there, such as `MSBuildProjectName`.
> **Important**: Do not mix VSTest-based and MTP-based .NET test projects in the same solution or run configuration -- this is an unsupported scenario.
When to Use
- Switching from VSTest to Microsoft.Testing.Platform for any supported test framework
- Enabling `dotnet run` / `dotnet watch` / direct executable execution for test projects
- Enabling Native AOT or trimmed test execution
- Replacing `vstest.console.exe` with `dotnet test` on MTP
- Updating CI/CD pipelines from the VSTest task to the .NET Core CLI task
- Updating `dotnet test` arguments from VSTest syntax to MTP syntax
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 `migrate-mstest-v1v2-to-v3` or `migrate-mstest-v3-to-v4`
Inputs
| Input | Required | Description | |-------|----------|-------------| | Project or solution path | No | The `.csproj`, `.sln`, or `.slnx` entry point containing test projects. **Discover it yourself** by globbing the working directory; ask only when nothing is found or the choice is genuinely ambiguous | | Test framework | No | MSTest, NUnit, xUnit.net v2, or xUnit.net v3. Auto-detected from package references | | .NET SDK version | No | Determines `dotnet test` integration mode. Prefer the repository's `global.json` or explicitly stated CI SDK; use host `dotnet --version` only when the repository does not pin or state one | | CI/CD pipeline files | No | Paths to pipeline definitions that invoke `vstest.console` or `dotnet test` |
Execution and Answer Contract
- Discover project, props, `global.json`, and pipeline files in the current working directory. Open literal search results; the skill directory is not the user's repository. Continue after skill activation and do not ask for a discoverable path.
- For an implementation request, edit the files, then validate the effective MSBuild properties, the translated command, test counts, and requested artifacts. For a question, provide one exact command/configuration for the detected SDK and framework rather than a menu of near-equivalents.
- Preserve all build arguments and avoid introducing `--no-build`, new settings files, or unrelated package upgrades. Never retain `--settings <file>` unless that file exists.
- For .NET 9 and earlier, show the `--` separator. For .NET 10 native MTP mode, explicitly say to remove it.
- When suppressing exit code 8 is intentional, warn that broad suppression can hide an accidental empty run caused by a bad filter; scope it to the known zero-test project/configuration.
- For an exit-code-8 question, show all three concrete forms: `--ignore-exit-code 8`, `TestingPlatformCommandLineArguments`, and `TESTINGPLATFORM_EXITCODE_IGNORE=8`.
- For xUnit v3 filters, give the directly usable `--filter-class`/`--filter-method`/`--filter-trait` command and explain AND behavior. When the resolved xUnit version supports it, include `--filter-query` path syntax for complex expressions and link the xUnit query-filter documentation.
- When translating reporters, coverage, or dumps, name each required package in the answer; a correct-looking option without its owning extension package is incomplete.
- Final results must name the framework runner opt-in, repository-selected SDK integration mode, exact translated command, extension packages, and verification evidence.
Workflow
Step 1: Assess the solution
1. Identify the test framework for each test project -- see the `platform-detection` skill for the package-to-framework mapping. Key indicators:
- **MSTest**: References `MSTest` or `MSTest.TestAdapter`, or uses `MSTest.Sdk` (with `<IsTestApplication>` not set to `false`). Note: `MSTest.TestFramework` alone is a library dependency, not a test project.
- **NUnit**: References `NUnit3TestAdapter`
- **xUnit.net**: References `xunit` and `xunit.runner.visualstudio`
2. Resolve the SDK used by the repository/CI from `global.json` or explicit user context. Fall back to `dotnet --versi
Read more
name: migrate-vstest-to-mtp description: > Use this skill before answering, planning, or editing whenever .NET tests or CI are switching from VSTest to Microsoft.Testing.Platform (MTP), or an MTP migration behaves differently. Triggers include "switch from VSTest"; MSTest/NUnit/xUnit MTP enablement; OutputType=Exe only for test projects in Directory.Build.props; EnableMSTestRunner, EnableNUnitRunner, UseMicrosoftTestingPlatformRunner, or YTest.MTP.XUnit2; .NET 10 global.json test.runner and TestingPlatformDotnetTestSupport; translating VSTest filters, logger, coverage, blame, or dump arguments; replacing VSTest@3; and exit code 8 or zero tests. Also use for xUnit v3 MTP filters during a v2-to-v3 upgrade. Do not use for framework conversion, TFM, UWP, or WinUI. license: MIT
VSTest -> Microsoft.Testing.Platform Migration
Migrate a .NET test solution from VSTest to Microsoft.Testing.Platform (MTP). The outcome is a solution where all test projects run on MTP, `dotnet test` works correctly, and CI/CD pipelines are updated.
First Action
Inspect the supplied project, `Directory.Build.props`, `global.json`, and CI files before searching the web or answering from memory. Resolve the framework and SDK mode first: .NET 9 and earlier use the compatibility property plus the `--` separator; .NET 10 native MTP uses `global.json`, removes that property, and passes MTP arguments without the separator. For central properties, never condition on `IsTestProject` in `Directory.Build.props`; use a property already available there, such as `MSBuildProjectName`.
> **Important**: Do not mix VSTest-based and MTP-based .NET test projects in the same solution or run configuration -- this is an unsupported scenario.
When to Use
- Switching from VSTest to Microsoft.Testing.Platform for any supported test framework
- Enabling `dotnet run` / `dotnet watch` / direct executable execution for test projects
- Enabling Native AOT or trimmed test execution
- Replacing `vstest.console.exe` with `dotnet test` on MTP
- Updating CI/CD pipelines from the VSTest task to the .NET Core CLI task
- Updating `dotnet test` arguments from VSTest syntax to MTP syntax
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 `migrate-mstest-v1v2-to-v3` or `migrate-mstest-v3-to-v4`
Inputs
| Input | Required | Description | |-------|----------|-------------| | Project or solution path | No | The `.csproj`, `.sln`, or `.slnx` entry point containing test projects. **Discover it yourself** by globbing the working directory; ask only when nothing is found or the choice is genuinely ambiguous | | Test framework | No | MSTest, NUnit, xUnit.net v2, or xUnit.net v3. Auto-detected from package references | | .NET SDK version | No | Determines `dotnet test` integration mode. Prefer the repository's `global.json` or explicitly stated CI SDK; use host `dotnet --version` only when the repository does not pin or state one | | CI/CD pipeline files | No | Paths to pipeline definitions that invoke `vstest.console` or `dotnet test` |
Execution and Answer Contract
- Discover project, props, `global.json`, and pipeline files in the current working directory. Open literal search results; the skill directory is not the user's repository. Continue after skill activation and do not ask for a discoverable path.
- For an implementation request, edit the files, then validate the effective MSBuild properties, the translated command, test counts, and requested artifacts. For a question, provide one exact command/configuration for the detected SDK and framework rather than a menu of near-equivalents.
- Preserve all build arguments and avoid introducing `--no-build`, new settings files, or unrelated package upgrades. Never retain `--settings <file>` unless that file exists.
- For .NET 9 and earlier, show the `--` separator. For .NET 10 native MTP mode, explicitly say to remove it.
- When suppressing exit code 8 is intentional, warn that broad suppression can hide an accidental empty run caused by a bad filter; scope it to the known zero-test project/configuration.
- For an exit-code-8 question, show all three concrete forms: `--ignore-exit-code 8`, `TestingPlatformCommandLineArguments`, and `TESTINGPLATFORM_EXITCODE_IGNORE=8`.
- For xUnit v3 filters, give the directly usable `--filter-class`/`--filter-method`/`--filter-trait` command and explain AND behavior. When the resolved xUnit version supports it, include `--filter-query` path syntax for complex expressions and link the xUnit query-filter documentation.
- When translating reporters, coverage, or dumps, name each required package in the answer; a correct-looking option without its owning extension package is incomplete.
- Final results must name the framework runner opt-in, repository-selected SDK integration mode, exact translated command, extension packages, and verification evidence.
Workflow
Step 1: Assess the solution
1. Identify the test framework for each test project -- see the `platform-detection` skill for the package-to-framework mapping. Key indicators:
- **MSTest**: References `MSTest` or `MSTest.TestAdapter`, or uses `MSTest.Sdk` (with `<IsTestApplication>` not set to `false`). Note: `MSTest.TestFramework` alone is a library dependency, not a test project.
- **NUnit**: References `NUnit3TestAdapter`
- **xUnit.net**: References `xunit` and `xunit.runner.visualstudio`
2. Resolve the SDK used by the repository/CI from `global.json` or explicit user context. Fall back to `dotnet --versi
This repository contains the .NET team's curated set of portable skills and host-specific custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io.
Other skills on skills.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about migrate-vstest-to-mtp.
- Which coding agents can use migrate-vstest-to-mtp?
- migrate-vstest-to-mtp installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

