Platform Upgrades & Migration v0.1.7

MSTest v1/v2 -> v3 Migration

Migrate MSTest v1/v2 projects to MSTest v3, and fix v1/v2-to-v3 breaking changes that surface after the packages are already at 3.x. USE FOR: removing v1 Microsoft.VisualStudio.QualityTools.UnitTestFramework assembly references; moving MSTest.TestFramework/TestAdapter 1.x-2.x to 3.x, the MSTest metapackage, or MSTest.Sdk; tests that broke after a 2.x-to-3.x bump -- CS0411/CS1503 on Assert.AreEqual/AreNotEqual/AreSame once the object overloads became generic, and DataRow strict type matching (1L vs 1) that builds with MSTEST0014 but fails at run time; .testsettings/LegacySettings to .runsettings (DeploymentEnabled, per-test MSTest TestTimeout); v3 timeout behavior; TFMs v3 dropped (net5.0, .NET Fx below 4.6.2, netstandard1.0). Applies even when the project already references MSTest 3.x, if a v1/v2-era setting or error remains. Keeps the current runner. DO NOT USE FOR: MSTest v4 (use migrate-mstest-v3-to-v4 next), clean v3 projects with no v1/v2 leftovers, other test frameworks, or VSTest-to-MTP.

Workflow

Step 1: Assess the project

  1. Locate the project first: glob the working directory for *.csproj, *.sln,

*.slnx, Directory.Build.props, Directory.Packages.props, and *.testsettings. Do this before asking the user anything, and open whatever it returns at exactly the path it reported (see the note under Inputs).

  1. In one discovery pass, batch-read project and central configuration files, search for affected APIs/settings, and identify which MSTest version is currently in use:

- Assembly reference: Look for Microsoft.VisualStudio.QualityTools.UnitTestFramework in project references -> MSTest v1 - NuGet packages: Check MSTest.TestFramework and MSTest.TestAdapter package versions -> v1 if 1.x, v2 if 2.x

  1. Check whether the target framework is dropped in v3 (see Step 4).
  2. Run the existing test command. Record discovered, passed, failed, and skipped counts as the parity baseline.

Step 2: Remove v1 assembly references (if applicable)

If the project uses MSTest v1 via assembly references:

  1. Remove the reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll

- In SDK-style projects, remove the <Reference> element from the .csproj - In non-SDK-style projects, remove via Visual Studio Solution Explorer -> References -> right-click -> Remove

  1. Save the project file

Step 3: Update packages to MSTest v3

Use one package model; do not leave duplicate framework/adapter references.

Default -- install the MSTest metapackage:

Remove individual MSTest.TestFramework and MSTest.TestAdapter package references and replace with the unified MSTest metapackage:

<PackageReference Include="MSTest" Version="3.8.0" />

Keep Microsoft.NET.Test.Sdk when the project remains on VSTest, but update it to a version compatible with the selected MSTest release. For example, MSTest 3.8.0 requires Microsoft.NET.Test.Sdk 17.13.0 or later; leaving an older explicit version causes NU1605. If package versions are centrally managed, update Directory.Packages.props rather than adding inline versions.

Use MSTest.Sdk only when the user requests it or the repository already standardizes on it (SDK-style projects only):

Change <Project Sdk="Microsoft.NET.Sdk"> to <Project Sdk="MSTest.Sdk/3.8.0">. MSTest.Sdk automatically provides the MSTest framework, adapter, and analyzers.

> Important: MSTest.Sdk defaults to Microsoft.Testing.Platform (MTP). When preserving VSTest, set <UseVSTest>true</UseVSTest>; the SDK then supplies the required Microsoft.NET.Test.Sdk reference. Do not switch runners merely as a side effect of the framework upgrade.

When switching to MSTest.Sdk, remove these (SDK provides them automatically):

  • Packages: MSTest, MSTest.TestFramework, MSTest.TestAdapter, MSTest.Analyzers, Microsoft.NET.Test.Sdk
  • Properties: <EnableMSTestRunner>, <OutputType>Exe</OutputType>, <IsPackable>false</IsPackable>, <IsTestProject>true</IsTestProject>

Step 4: Update target frameworks if needed

MSTest v3 supports .NET 6+, .NET Core 3.1, .NET Framework 4.6.2+, .NET Standard 2.0, UWP 16299+, and WinUI 18362+. .NET Core 3.1 is end-of-life but remains supported by MSTest v3; preserve it during this framework-only migration and recommend a separate runtime upgrade. If the project targets a framework version dropped by MSTest v3, update to a supported one:

| Dropped | Recommended replacement | |---------|------------------------| | .NET 5 | .NET 8.0 (current LTS) or .NET 6+ | | .NET Framework < 4.6.2 | .NET Framework 4.6.2 | | .NET Standard 1.0 | .NET Standard 2.0 | | UWP < 16299 | UWP 16299 | | WinUI < 18362 | WinUI 18362 |

> Note: .NET 6, .NET 8, and .NET 9 are all supported by MSTest v3. Do not change TFMs that are already supported.

Step 5: Resolve build errors and breaking changes

Search the supplied files first and fix only breaking changes that are present. A successful build does not prove compatibility; some failures surface only as analyzer warnings or during test execution.

Assertion overloads -- MSTest v3 replaced Assert.AreEqual(object, object) and AreNotEqual(object, object) with the generic AreEqual<T>(T?, T?). This breaks only where T can no longer be inferred, which the compiler reports as CS0411 (or CS1503 for unrelated argument types):

// Breaks -- string and int have no common inferred type:
Assert.AreEqual(referenceCode, numericId);   // CS0411
// Fix -- name the type argument explicitly:
Assert.AreEqual<object>(referenceCode, numericId);

Two object-typed arguments still infer T = object and compile untouched, as do ordinary typed assertions like Assert.AreEqual("A-3", order.Reference). Fix only the call sites the compiler rejects. Widening every assertion in the file to <object> also compiles, so nothing will flag it -- but it discards the type checking v3 added, which is the entire point of the change.

DataRow strict type matching -- argument types must match parameter types exactly. This is not a compile error: the row builds (with MSTEST0014) and fails at run time with "Test data doesn't match method parameters".

// Fails at run time: 1L (long) does not bind to an int parameter -> use 1
// Fails at run time: 1.0 (double) does not bind to a float parameter -> use 1.0f
// Still binds: 1 (int) to a long parameter -- widening conversions are accepted

Preserve method parameter types unless independently wrong. dotnet build may succeed with MSTEST0014; run the test to prove each row binds and executes.

Rows with more than 16 arguments -- leave them alone unless the compiler actually emits CS1729. The cap existed only in 3.0.1/3.0.2 (removed in 3.0.3), so wrapping extras in an object[], casting to object, or splitting the method just rewrites a correct test.

Timeout behavior -- unified across .NET Core and .NET Framework. Verify [Timeout] values still work.

Step 6: Replace .testsettings with .runsettings

The .testsettings file and <LegacySettings> are no longer supported in MSTest v3. Delete the `.testsettings` file and create a .runsettings file -- do not keep both. Consolidate all MSTest configuration under one <MSTest> element; do not create an <MSTestV2> section.

Key mappings:

| .testsettings | .runsettings equivalent | |---|---| | TestTimeout property | <MSTest><TestTimeout>30000</TestTimeout></MSTest> | | Deployment config | <MSTest><DeploymentEnabled>true</DeploymentEnabled></MSTest> or remove | | Assembly resolution settings | Remove -- not needed in modern .NET | | Data collectors | <DataCollectionRunSettings><DataCollectors> section |

> Important: Map timeout to <MSTest><TestTimeout> (per-test), not <TestSessionTimeout> (session-wide). Remove <LegacySettings> entirely.

Step 7: Verify

  1. Run the same test command, filter, and configuration used for the baseline. dotnet test builds by default; run a separate build only to isolate a compilation failure.
  2. Compare discovered, passed, failed, and skipped counts to the pre-migration baseline.
  3. Investigate every count difference; do not accept silently dropped tests or data rows.
  4. Confirm no QualityTools reference, 1.x/2.x MSTest package, .testsettings, or <LegacySettings> remains.

Related skills