Platform Upgrades & Migration v0.1.8

MSTest v1/v2 -> v3 Migration

Use this skill before answering or editing whenever an MSTest v1/v2 project is being upgraded or repaired for v3. Triggers include QualityTools assembly references; MSTest.TestFramework/TestAdapter 1.x-2.x; "upgrade to MSTest v3"; comparing v1 and v2 migration paths; choosing MSTest or MSTest.Sdk; CS0411/CS1503 after a v3 package bump; DataRow type mismatch, MSTEST0014, or "Test data doesn't match method parameters"; .testsettings/LegacySettings to .runsettings; timeout changes; and net5.0 or other dropped v3 TFMs. Still use it when packages say 3.x but migration source errors or legacy settings remain. Preserve VSTest/MTP. Do not use for a clean v3 project, v3-to-v4, framework conversion, or runner-only migration.

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 the > project itself must remain on VSTest, set <UseVSTest>true</UseVSTest>. MSTest.Sdk > v3 also supplies Microsoft.NET.Test.Sdk in MTP mode, so a separate transitional > vstest.console invocation does not by itself require changing the primary runner. > 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.

Update every project, CI command, or IDE setting that explicitly selected the old .testsettings path to select the new .runsettings path. When a VSTest project must preserve behavior but the legacy file was never selected, make the new file effective with RunSettingsFilePath. For MTP, use the framework-supported --settings path or existing MTP configuration instead of assuming the VSTest MSBuild property is honored.

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