diff --git a/plugins/dotnet-test/skills/migrate-xunit-to-mstest/SKILL.md b/plugins/dotnet-test/skills/migrate-xunit-to-mstest/SKILL.md
index 10ee21a192..fba4013c46 100644
--- a/plugins/dotnet-test/skills/migrate-xunit-to-mstest/SKILL.md
+++ b/plugins/dotnet-test/skills/migrate-xunit-to-mstest/SKILL.md
@@ -150,13 +150,15 @@ With the pin in `global.json`, the project line simplifies to `` to the project (it's noise) and skip the per-file `using Microsoft.VisualStudio.TestTools.UnitTesting;` in Step 4 -- you only need it for projects on Option A (the `MSTest` metapackage).
+
### Step 3: Update project configuration
1. **Preserve the runner.** Confirm the platform decision from Step 1 still holds after Step 2. Common mistakes:
- Switching to `MSTest.Sdk` without `UseVSTest=true` silently flips a VSTest project to MTP. Add `true` to the project (the SDK pulls in `Microsoft.NET.Test.Sdk` automatically -- no manual `PackageReference` needed).
- `true` only affects the `dotnet run` entry point and is **not** a runner switch in Test Explorer or `dotnet test`. Do not infer the platform from this property in either direction -- defer to the `platform-detection` skill (see Step 1).
2. Delete `xunit.runner.json` and port any settings you need (parallelization, `[CollectionBehavior]`, `appDomain`) per Step 11's "xunit.runner.json -> MSTest" sub-table. The settings have no direct MSBuild-property mapping.
-3. Remove `using Xunit;` and `using Xunit.Abstractions;` from C# files (the rewriter will add `using Microsoft.VisualStudio.TestTools.UnitTesting;` instead in Step 4).
+3. Remove `using Xunit;` and `using Xunit.Abstractions;` from C# files. For **Option A** (`MSTest` metapackage), add `using Microsoft.VisualStudio.TestTools.UnitTesting;` per file (Step 4 covers this alongside the other rewrites). For **Option B** (`MSTest.Sdk`), skip the per-file using -- the SDK provides it as an implicit global using.
### Step 4: Convert test classes and methods
@@ -166,7 +168,7 @@ Apply these rewrites to every C# test file. Class-level first, then method-level
- Add `[TestClass]` to every class that contained xUnit `[Fact]`/`[Theory]` methods (xUnit had no class-level requirement).
- **Preserve the original class hierarchy.** xUnit projects often use base/derived test classes (shared setup, helper assertions, generic base fixtures); marking classes `sealed` would break that pattern. Sealing is an optional follow-up handled by `writing-mstest-tests`, not part of the mechanical migration.
-- Replace `using Xunit;` / `using Xunit.Abstractions;` with `using Microsoft.VisualStudio.TestTools.UnitTesting;`.
+- Replace `using Xunit;` / `using Xunit.Abstractions;` with `using Microsoft.VisualStudio.TestTools.UnitTesting;`. **On Option B (`MSTest.Sdk`), skip adding the MSTest using** -- the SDK provides it as an implicit global using, so just remove the `using Xunit;` / `using Xunit.Abstractions;` lines (Step 2 and Step 3 cover this).
**Methods:**
@@ -213,7 +215,9 @@ Most common cases inline. For the full table including string/collection/type/nu
| `Assert.Throws(() => ...)` | **`Assert.ThrowsExactly(() => ...)`** (see trap below) |
| `Assert.ThrowsAny(() => ...)` | **`Assert.Throws(() => ...)`** |
| `await Assert.ThrowsAsync(...)` | `await Assert.ThrowsExactlyAsync(...)` |
-| `Assert.IsType(x)` / `Assert.IsAssignableFrom(x)` | `Assert.IsInstanceOfType(x)` (MSTest v4 returns the typed value) |
+| `Assert.IsType(x)` (exact-type check, returns `T`) | `Assert.IsExactInstanceOfType(x)` (MSTest 4.1+, returns `T`) -- **not** `Assert.IsInstanceOfType`, which is assignable/is-a and silently weakens the assertion |
+| `Assert.IsNotType(x)` (exact-type check) | `Assert.IsNotExactInstanceOfType(x)` (MSTest 4.1+) |
+| `Assert.IsAssignableFrom(x)` | `Assert.IsInstanceOfType(x)` (MSTest v4 returns the typed value) |
| `Assert.Empty(coll)` / `Assert.NotEmpty(coll)` | `Assert.IsEmpty(coll)` / `Assert.IsNotEmpty(coll)` |
| `Assert.Single(coll)` | `var item = Assert.ContainsSingle(coll);` |
| `Assert.Contains(item, coll)` / `Assert.DoesNotContain(...)` | Same -- `Assert.Contains` / `Assert.DoesNotContain` |
diff --git a/plugins/dotnet-test/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md b/plugins/dotnet-test/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md
index 1985fdb904..9f90fe7406 100644
--- a/plugins/dotnet-test/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md
+++ b/plugins/dotnet-test/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md
@@ -110,10 +110,12 @@ Target framework throughout: **MSTest v4** (the few v3-only spellings are explic
| xUnit | MSTest |
|---|---|
-| `Assert.IsType(x)` (exact type, returns `T`) | MSTest v4: `var t = Assert.IsInstanceOfType(x);` (semantically *assignable*, not exact); for exact-type, follow with `Assert.AreEqual(typeof(T), x.GetType())` |
-| `Assert.IsNotType(x)` (exact type) | `Assert.IsNotInstanceOfType(x);` plus `Assert.AreNotEqual(typeof(T), x.GetType())` if exact-type matters |
-| `Assert.IsAssignableFrom(x)` | `Assert.IsInstanceOfType(x)` -- semantically equivalent |
+| `Assert.IsType(x)` (exact type, returns `T`) | `var t = Assert.IsExactInstanceOfType(x);` (MSTest 4.1+; returns the typed value, exact match) |
+| `Assert.IsNotType(x)` (exact type) | `Assert.IsNotExactInstanceOfType(x);` (MSTest 4.1+) |
+| `Assert.IsAssignableFrom(x)` | `Assert.IsInstanceOfType(x)` -- semantically equivalent (assignable-from check) |
+> MSTest 4.1+ adds `Assert.IsExactInstanceOfType(x)` -- the proper equivalent of xUnit's exact-type `Assert.IsType` (returns `T`, single call). On pre-4.1 MSTest, fall back to `var t = Assert.IsInstanceOfType(x); Assert.AreEqual(typeof(T), x.GetType());`. `Assert.IsInstanceOfType(x)` on its own is **assignable-only** (= xUnit `Assert.IsAssignableFrom`); silently mapping `IsType` to it loses exact-type semantics.
+>
> MSTest v4's `Assert.IsInstanceOfType(x)` returns the typed value (no out param). MSTest v3 uses `Assert.IsInstanceOfType(x, out var typed)`.
### 3.4 Numeric / comparison
@@ -150,8 +152,8 @@ Target framework throughout: **MSTest v4** (the few v3-only spellings are explic
| `Assert.Single(collection, predicate)` | `var item = Assert.ContainsSingle(collection.Where(predicate));` |
| `Assert.Collection(items, e1 => ..., e2 => ...)` | **Manual** -- assert count, then per-element. No idiomatic MSTest equivalent |
| `Assert.All(items, x => assertion(x))` | **Manual** -- `foreach (var x in items) assertion(x);` |
-| `Assert.Equal(expected, actual)` on `IEnumerable` (element-wise) | `CollectionAssert.AreEqual(expected.ToList(), actual.ToList())` (`IList` required) |
-| `Assert.Equal(expected, actual, comparer)` on collections | `CollectionAssert.AreEqual(expected.ToList(), actual.ToList(), comparer)` |
+| `Assert.Equal(expected, actual)` on `IEnumerable` (element-wise) | `Assert.AreSequenceEqual(expected, actual)` (MSTest 4.3+); pre-4.3: `CollectionAssert.AreEqual(expected.ToList(), actual.ToList())` (`IList` required). Plain `Assert.AreEqual` does **not** compare element-wise (MSTEST0065). |
+| `Assert.Equal(expected, actual, comparer)` on collections | `Assert.AreSequenceEqual(expected, actual, comparer)` (MSTest 4.3+); pre-4.3: `CollectionAssert.AreEqual(expected.ToList(), actual.ToList(), comparer)` |
| `Assert.Distinct(collection)` | **Manual** -- `Assert.AreEqual(collection.Count, collection.Distinct().Count())` |
| `Assert.Superset(expected, actual)` | **Manual** -- `Assert.IsTrue(expected.IsSubsetOf(actual))` if both are `HashSet` |
@@ -365,6 +367,13 @@ Prefer pinning the `MSTest.Sdk` version in `global.json` (especially in solution
With the pin in `global.json`, the project line simplifies to ``.
+`MSTest.Sdk` adds `Microsoft.VisualStudio.TestTools.UnitTesting` as an **implicit global using**, so:
+
+- **Do not** add `` to the project file -- it's redundant noise.
+- **Do not** add `using Microsoft.VisualStudio.TestTools.UnitTesting;` to each test file -- it's already in scope.
+
+(Option A -- the `MSTest` metapackage -- does not bring the global using; per-file `using Microsoft.VisualStudio.TestTools.UnitTesting;` is still required there.)
+
## 10. Companion / extension libraries
| xUnit companion | MSTest equivalent |
@@ -374,6 +383,6 @@ With the pin in `global.json`, the project line simplifies to `