migrate-xunit-to-mstest: add learnings from dotnet/sdk migration#756
Conversation
Refines the skill based on a real migration of 5 test projects in dotnet/sdk: - MSTest.Sdk implicit global using: do not add `<Using Include='Microsoft.VisualStudio.TestTools.UnitTesting' />` or per-file `using` in MSTest.Sdk projects (it's already in scope). Note Option A (`MSTest` metapackage) still needs the per-file using. - `Assert.IsExactInstanceOfType<T>` (MSTest 4.1+) is the proper single-call equivalent of xUnit's exact-type `Assert.IsType<T>`; previous guidance silently degraded it to assignable semantics (closes dotnet#755). - `Assert.AreSequenceEqual` (MSTest 4.3+) is the modern element-wise equivalent of xUnit's `Assert.Equal` on `IEnumerable<T>`, avoiding the `CollectionAssert` + `.ToList()` dance and the MSTEST0065 trap on plain `AreEqual`. - Clarify `AwesomeAssertions` ships in the `FluentAssertions` namespace, so it's a no-source-change swap. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Folds learnings discovered while migrating dotnet/sdk to MSTest.Sdk: - MSTest.Sdk implicit global using note - Assert.IsExactInstanceOfType<T> (MSTest 4.1+) for xUnit Assert.IsType<T> - Assert.AreSequenceEqual (MSTest 4.3+) over CollectionAssert.AreEqual - AwesomeAssertions namespace clarification Keeps the sdk-local copy in sync with the upstream PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates the migrate-xunit-to-mstest skill documentation to incorporate recent learnings from dotnet/sdk’s xUnit → MSTest migration, with a focus on preserving assertion semantics and reducing migration noise when using MSTest.Sdk.
Changes:
- Document
MSTest.Sdk’s implicit global using forMicrosoft.VisualStudio.TestTools.UnitTestingand warn against redundant per-project/per-file additions. - Update type-check guidance to use
Assert.IsExactInstanceOfType<T>/Assert.IsNotExactInstanceOfType<T>(MSTest 4.1+) to preserve xUnit’s exact-type semantics. - Update collection equality guidance to prefer
Assert.AreSequenceEqual(MSTest 4.3+) with a pre-4.3 fallback.
Show a summary per file
| File | Description |
|---|---|
| plugins/dotnet-test/skills/migrate-xunit-to-mstest/SKILL.md | Adds guidance about MSTest.Sdk implicit global using and updates assertion mapping guidance. |
| plugins/dotnet-test/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md | Refreshes the cheatsheet with newer MSTest APIs and adds clarifying notes for common migration pitfalls. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 2
… equivalence Address dotnet/sdk#54727 review comment: the Step 6 summary table conflated xUnit's exact-type Assert.IsType<T> and assignable Assert.IsAssignableFrom<T> into a single row, which implies both map interchangeably even though their semantics differ. Split into three rows -- IsType<T> -> IsExactInstanceOfType<T>, IsNotType<T> -> IsNotExactInstanceOfType<T>, IsAssignableFrom<T> -> IsInstanceOfType<T> -- and explicitly call out the silent-weakening trap. The cheatsheet already maps these correctly; this aligns the SKILL.md summary with the cheatsheet so the at-a-glance table doesn't suggest a wrong mapping. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… equivalence Addresses review comment from copilot-pull-request-reviewer: the Step 6 summary table conflated xUnit's exact-type Assert.IsType<T> and assignable Assert.IsAssignableFrom<T> into a single row, which implies both map interchangeably even though their semantics differ. Split into three rows -- IsType<T> -> IsExactInstanceOfType<T>, IsNotType<T> -> IsNotExactInstanceOfType<T>, IsAssignableFrom<T> -> IsInstanceOfType<T> -- and explicitly call out the silent-weakening trap. The cheatsheet already mapped these correctly; this aligns the SKILL.md summary so the at-a-glance table doesn't suggest a wrong mapping. Mirrored in dotnet/skills#756. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…on B Address review feedback on dotnet#756: Step 3 said to skip the per-file 'using Microsoft.VisualStudio.TestTools.UnitTesting;' on Option B (MSTest.Sdk provides it as an implicit global using), but Step 4 unconditionally instructed replacing xUnit usings with that MSTest using -- so an agent following Step 4 literally would re-add the redundant using on Option B projects. Also drop the dangling 'Step 4 rewriter' phrasing in Step 3 (there is no rewriter in Step 4, just a list of mechanical rewrites the agent applies). Step 4 now explicitly says to skip the MSTest using on Option B and only remove the 'using Xunit;' lines, matching Step 2's note and Step 3's branch instructions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/evaluate |
Skill Validation Results
[1] Model: claude-opus-4.6 | Judge: claude-opus-4.6 🔍 Full Results - additional metrics and failure investigation steps
▶ Sessions Visualisation -- interactive replay of all evaluation sessions |
|
✅ Evaluation passed for |
Folds learnings from a recent xUnit → MSTest migration in dotnet/sdk (5 stacked PRs: dotnet/sdk#54722, #54723, #54724, #54725, #54726) back into this skill.
Changes
1.
MSTest.Sdkimplicit global using (new)MSTest.SdkaddsMicrosoft.VisualStudio.TestTools.UnitTestingas an implicit global using. The skill previously didn't say so, which led to:<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />being added to every migrated csproj (redundant noise; flagged in review).using Microsoft.VisualStudio.TestTools.UnitTesting;being added to every test file (also redundant).Added a callout in SKILL.md Step 2 (Option B) and Step 3 and a section in cheatsheet §9 (Option B) with
Do notbullets. Option A (theMSTestmetapackage) still needs the per-file using -- noted explicitly.2.
Assert.IsExactInstanceOfType<T>(closes #755)xUnit's
Assert.IsType<T>is exact type. The current cheatsheet recommendedAssert.IsInstanceOfType<T>(assignable-from) plus a follow-upAssert.AreEqual(typeof(T), x.GetType())workaround. MSTest 4.1+ hasAssert.IsExactInstanceOfType<T>(microsoft/testfx#4633) -- single call, exact match, returnsT. Same goes forAssert.IsNotExactInstanceOfType<T>.This was a real regression in dotnet/sdk#54722 (39 sites silently weakened from exact to assignable, caught by a reviewer; re-flipped in a follow-up commit). Updated SKILL.md inline mapping table and cheatsheet §3.3 with the modern API; kept the pre-4.1 fallback as a note for legacy projects.
3.
Assert.AreSequenceEqual(MSTest 4.3+)The cheatsheet recommended
CollectionAssert.AreEqual(expected.ToList(), actual.ToList())for xUnit's element-wiseAssert.EqualonIEnumerable<T>. MSTest 4.3+ addedAssert.AreSequenceEqual(expected, actual)which:IEnumerable<T>directly (no.ToList()),CollectionAssert,Assert.AreEqualsilently does a reference compare on collections.Updated cheatsheet §3.6 to recommend
AreSequenceEqual(with pre-4.3 fallback noted).4.
AwesomeAssertionsnamespace noteSection 10 already said "keep -- assertion libraries are framework-agnostic" for
AwesomeAssertions. Added a one-line clarification that it ships in theFluentAssertionsnamespace for API compat, so the swap is no-source-change. (This came up during PR review where a reviewer mistook<Using Include="FluentAssertions" />for a leftover.)Out of scope
StringAssert.*fallback from cheatsheet §3.5 -- theAssert.Contains/StartsWith/EndsWithflat-namespace API has been around since MSTest 3.8 and is the recommended target for current migrations, but the fallback is still useful for very old projects. Left alone.Validation
cc /cc @nohwnd @Youssef1313