/migrate-xunit-to-mstest
Convert .NET test projects from xUnit.net v2 or v3 to MSTest v4. Use for replacing xunit packages, [Fact]/[Theory], xUnit assertions, fixtures, ITestOutputHelper, traits, skips, and xUnit parallelization with MSTest equivalents while preserving the current VSTest or MTP runner.
$ npx -y skills add dotnet/skills --skill migrate-xunit-to-mstest --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/migrate-xunit-to-mstest
Context preview
The summary Claude sees to decide when to auto-load this skill.
Convert .NET test projects from xUnit.net v2 or v3 to MSTest v4. Use for replacing xunit packages, [Fact]/[Theory], xUnit assertions, fixtures, ITestOutputHelper, traits, skips, and xUnit parallelization with MSTest equivalents while preserving the current VSTest or MTP runner.
SKILL.md
migrate-xunit-to-mstest.SKILL.mdname: migrate-xunit-to-mstest
description: >
Convert .NET test projects from xUnit.net v2 or v3 to MSTest v4. Use for
replacing xunit packages, [Fact]/[Theory], xUnit assertions, fixtures,
ITestOutputHelper, traits, skips, and xUnit parallelization with MSTest
equivalents while preserving the current VSTest or MTP runner.
DO NOT USE FOR: xUnit v2 to v3 upgrades, MSTest version upgrades, migrations
from NUnit/TUnit, or runner-only VSTest to MTP migrations.
license: MIT
xUnit -> MSTest Migration
Convert xUnit.net v2 or v3 tests to MSTest v4 without changing the target framework or test platform. A successful migration builds, discovers the same tests, and preserves pass/fail results and execution semantics.
Scope
Use this skill only when the project contains xUnit packages or source and the user wants MSTest. If the project already uses MSTest and contains no xUnit tests, report that no framework migration is needed and make no changes.
Do not combine this framework conversion with a target-framework upgrade or VSTest/MTP migration. Complete and verify one migration before starting another.
Response Mode
- **Full migration request:** inspect the project, make the edits, build, and run tests. Do not stop after giving a plan.
- **Focused compile error or API question:** inspect the relevant code and apply only that mapping. Do not narrate the entire workflow.
- **Unsupported target framework:** stop before changing packages. MSTest v4 requires .NET 8+ or .NET Framework 4.6.2+ for test applications; offer a separately approved TFM upgrade or MSTest v3 as the intermediate target.
For detailed mappings and examples, search [`references/mapping-cheatsheet.md`](references/mapping-cheatsheet.md) for constructs actually present in the project and read only the matching sections. Do not load or reproduce the whole reference.
Fast Path
For a routine project migration, converge in four phases: one batched discovery read/search, one edit pass, one `dotnet test`, and one concise result. Do not:
- list a directory and then reread the same files through another tool
- try `dotnet test --no-restore` unless restore is already known to be current
- run separate restore, build, and test commands when `dotnet test` is sufficient
- rerun a passing test command or inspect unchanged files for confirmation
Use an existing CI/test result as the parity baseline when available. Run a new pre-edit baseline only when counts are unavailable and the migration contains data-driven tests, fixtures, skips, custom extensions, shared state, or other behavior whose parity cannot be established from source alone.
Workflow
1. Establish the baseline
1. In one discovery pass, batch-read the test projects plus `Directory.Build.props`, `Directory.Packages.props`, `global.json`, and runner configuration, and search the source for the high-risk constructs below. 2. State the detected source version:
- `xunit` 2.x and related packages -> xUnit v2
- `xunit.v3` or `xunit.v3.*` -> xUnit v3
3. Identify VSTest or MTP from the project and repository configuration. Use `platform-detection` only when the platform is ambiguous, and preserve the detected platform. 4. Record the target frameworks and stop if MSTest v4 does not support them. 5. If the Fast Path requires a new baseline, run the existing test command once and record discovered, passed, failed, and skipped counts. 6. Inventory high-risk constructs before editing:
- `IClassFixture`, `ICollectionFixture`, `CollectionDefinition`, custom `FactAttribute`/`TheoryAttribute`/`DataAttribute`
- `Assert.Throws`, `ThrowsAny`, `IsType`, `Record.Exception`, event assertions
- `ITestOutputHelper`, `TestContext.Current`, `IAsyncLifetime`
- `CollectionBehavior`, `xunit.runner.json`, shared static or external state
2. Replace packages without switching runners
Remove xUnit packages from project files and central package files. This includes `xunit*`, `xunit.v3.*`, `xunit.runner.visualstudio`, `YTest.MTP.XUnit2`, and xUnit-specific companion packages that are being replaced.
Default to the MSTest v4 metapackage for an incremental conversion:
<PackageReference Include="MSTest" Version="4.1.0" />
This keeps VSTest available through the metapackage's compatible `Microsoft.NET.Test.Sdk` dependency. Remove a stale explicit `Microsoft.NET.Test.Sdk` reference or update it to the minimum required by the chosen MSTest version (MSTest 4.1.0 requires 18.0.1+); otherwise restore fails with `NU1605`. Use `MSTest.Sdk` only when the project already uses it elsewhere or the user explicitly requests it. `MSTest.Sdk` defaults to MTP, so add `<UseVSTest>true</UseVSTest>` when preserving VSTest.
Do not change `TargetFramework`. Remove `xunit.runner.json` only after porting its relevant settings.
3. Perform the mechanical conversion
Apply the common rewrites first:
| xUnit | MSTest | |---|---| | no class attribute | `[TestClass]` | | `[Fact]` | `[TestMethod]` | | `[Theory]` + `[InlineData]` | `[TestMethod]` + `[DataRow]` | | `[MemberData]` | `[DynamicData]` | | `[Fact(Skip = "...")]` | `[TestMethod]` + `[Ignore("...")]` | | `[Trait("Category", value)]` | `[TestCategory(value)]` | | `[Trait("Owner", value)]` | `[Owner(value)]` | | other `[Trait(key, value)]` | `[TestProperty(key, value)]` | | `Assert.Equal` / `NotEqual` | `Assert.AreEqual` / `AreNotEqual` | | `Assert.True` / `False` | `Assert.IsTrue` / `IsFalse` | | `Assert.Null` / `NotNull` | `Assert.IsNull` / `IsNotNull` |
Remove `using Xunit;` and `using Xunit.Abstractions;`. Add `using Microsoft.VisualStudio.TestTools.UnitTesting;` for the metapackage option; `MSTest.Sdk` supplies it as an implicit global using.
Preserve existing class inheritance. Do not mechanically seal classes.
4. Resolve semantic mappings
Load the mapping cheatsheet for every high-risk construct found in Step 1. These rules are mandatory:
- xUnit `Assert.Throws<T>` is exact-type and maps to M
Read more
name: migrate-xunit-to-mstest description: > Convert .NET test projects from xUnit.net v2 or v3 to MSTest v4. Use for replacing xunit packages, [Fact]/[Theory], xUnit assertions, fixtures, ITestOutputHelper, traits, skips, and xUnit parallelization with MSTest equivalents while preserving the current VSTest or MTP runner. DO NOT USE FOR: xUnit v2 to v3 upgrades, MSTest version upgrades, migrations from NUnit/TUnit, or runner-only VSTest to MTP migrations. license: MIT
xUnit -> MSTest Migration
Convert xUnit.net v2 or v3 tests to MSTest v4 without changing the target framework or test platform. A successful migration builds, discovers the same tests, and preserves pass/fail results and execution semantics.
Scope
Use this skill only when the project contains xUnit packages or source and the user wants MSTest. If the project already uses MSTest and contains no xUnit tests, report that no framework migration is needed and make no changes.
Do not combine this framework conversion with a target-framework upgrade or VSTest/MTP migration. Complete and verify one migration before starting another.
Response Mode
- **Full migration request:** inspect the project, make the edits, build, and run tests. Do not stop after giving a plan.
- **Focused compile error or API question:** inspect the relevant code and apply only that mapping. Do not narrate the entire workflow.
- **Unsupported target framework:** stop before changing packages. MSTest v4 requires .NET 8+ or .NET Framework 4.6.2+ for test applications; offer a separately approved TFM upgrade or MSTest v3 as the intermediate target.
For detailed mappings and examples, search [`references/mapping-cheatsheet.md`](references/mapping-cheatsheet.md) for constructs actually present in the project and read only the matching sections. Do not load or reproduce the whole reference.
Fast Path
For a routine project migration, converge in four phases: one batched discovery read/search, one edit pass, one `dotnet test`, and one concise result. Do not:
- list a directory and then reread the same files through another tool
- try `dotnet test --no-restore` unless restore is already known to be current
- run separate restore, build, and test commands when `dotnet test` is sufficient
- rerun a passing test command or inspect unchanged files for confirmation
Use an existing CI/test result as the parity baseline when available. Run a new pre-edit baseline only when counts are unavailable and the migration contains data-driven tests, fixtures, skips, custom extensions, shared state, or other behavior whose parity cannot be established from source alone.
Workflow
1. Establish the baseline
1. In one discovery pass, batch-read the test projects plus `Directory.Build.props`, `Directory.Packages.props`, `global.json`, and runner configuration, and search the source for the high-risk constructs below. 2. State the detected source version:
- `xunit` 2.x and related packages -> xUnit v2
- `xunit.v3` or `xunit.v3.*` -> xUnit v3
3. Identify VSTest or MTP from the project and repository configuration. Use `platform-detection` only when the platform is ambiguous, and preserve the detected platform. 4. Record the target frameworks and stop if MSTest v4 does not support them. 5. If the Fast Path requires a new baseline, run the existing test command once and record discovered, passed, failed, and skipped counts. 6. Inventory high-risk constructs before editing:
- `IClassFixture`, `ICollectionFixture`, `CollectionDefinition`, custom `FactAttribute`/`TheoryAttribute`/`DataAttribute`
- `Assert.Throws`, `ThrowsAny`, `IsType`, `Record.Exception`, event assertions
- `ITestOutputHelper`, `TestContext.Current`, `IAsyncLifetime`
- `CollectionBehavior`, `xunit.runner.json`, shared static or external state
2. Replace packages without switching runners
Remove xUnit packages from project files and central package files. This includes `xunit*`, `xunit.v3.*`, `xunit.runner.visualstudio`, `YTest.MTP.XUnit2`, and xUnit-specific companion packages that are being replaced.
Default to the MSTest v4 metapackage for an incremental conversion:
<PackageReference Include="MSTest" Version="4.1.0" />
This keeps VSTest available through the metapackage's compatible `Microsoft.NET.Test.Sdk` dependency. Remove a stale explicit `Microsoft.NET.Test.Sdk` reference or update it to the minimum required by the chosen MSTest version (MSTest 4.1.0 requires 18.0.1+); otherwise restore fails with `NU1605`. Use `MSTest.Sdk` only when the project already uses it elsewhere or the user explicitly requests it. `MSTest.Sdk` defaults to MTP, so add `<UseVSTest>true</UseVSTest>` when preserving VSTest.
Do not change `TargetFramework`. Remove `xunit.runner.json` only after porting its relevant settings.
3. Perform the mechanical conversion
Apply the common rewrites first:
| xUnit | MSTest | |---|---| | no class attribute | `[TestClass]` | | `[Fact]` | `[TestMethod]` | | `[Theory]` + `[InlineData]` | `[TestMethod]` + `[DataRow]` | | `[MemberData]` | `[DynamicData]` | | `[Fact(Skip = "...")]` | `[TestMethod]` + `[Ignore("...")]` | | `[Trait("Category", value)]` | `[TestCategory(value)]` | | `[Trait("Owner", value)]` | `[Owner(value)]` | | other `[Trait(key, value)]` | `[TestProperty(key, value)]` | | `Assert.Equal` / `NotEqual` | `Assert.AreEqual` / `AreNotEqual` | | `Assert.True` / `False` | `Assert.IsTrue` / `IsFalse` | | `Assert.Null` / `NotNull` | `Assert.IsNull` / `IsNotNull` |
Remove `using Xunit;` and `using Xunit.Abstractions;`. Add `using Microsoft.VisualStudio.TestTools.UnitTesting;` for the metapackage option; `MSTest.Sdk` supplies it as an implicit global using.
Preserve existing class inheritance. Do not mechanically seal classes.
4. Resolve semantic mappings
Load the mapping cheatsheet for every high-risk construct found in Step 1. These rules are mandatory:
- xUnit `Assert.Throws<T>` is exact-type and maps to M
This repository contains the .NET team's curated set of core skills and custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io. 📊 Dashboard - Accuracy and efficiency scoring trends for contained plugins (
Repo: dotnet/skills
Other skills on dotnet-skills.
- /csharp-scripts
Run file-based C# apps with the .NET CLI when the user explicitly wants C#/.NET code without creating a project. Use for C# language/API experiments, one-file C# apps, small multi-file C# apps composed with `#:include`/`#:exclude`, or C# file-based apps linked with `#:ref`. Do
Open skill - /dotnet-pinvoke
Correctly call native (C/C++) libraries from .NET using P/Invoke and LibraryImport. Covers function signatures, string marshalling, memory lifetime, SafeHandle, and cross-platform patterns. USE FOR: writing new P/Invoke or LibraryImport declarations, reviewing or debugging
Open skill - /nuget-trusted-publishing
Set up NuGet trusted publishing (OIDC) on a GitHub Actions repo — replaces long-lived API keys with short-lived tokens. USE FOR: trusted publishing, NuGet OIDC, keyless NuGet publish, migrate from NuGet API key, NuGet/login, secure NuGet publishing. DO NOT USE FOR: publishing to
Open skill - /technology-selection
Guides technology selection and implementation of AI and ML features in .NET 8+ applications using ML.NET, Microsoft.Extensions.AI (MEAI), Microsoft Agent Framework (MAF), GitHub Copilot SDK, ONNX Runtime, and OllamaSharp. Covers the full spectrum from classic ML through modern
Open skill - /configuring-opentelemetry-dotnet
Configure OpenTelemetry distributed tracing, metrics, and logging in ASP.NET Core using the .NET OpenTelemetry SDK. Use when adding observability, setting up OTLP exporters, creating custom metrics/spans, or troubleshooting distributed trace correlation.
Open skill - /convert-blazor-server-to-webapp
Guides conversion of a pre-.NET 8 Blazor Server app into a .NET 8+ Blazor Web App. USE FOR: migrating apps that use AddServerSideBlazor and MapBlazorHub to the AddRazorComponents/MapRazorComponents model, converting _Host.cshtml to an App.razor root component, replacing
Open skill

