Skip to content

Migrate containerize.UnitTests to MSTest.Sdk on MTP#54723

Open
Evangelink wants to merge 12 commits into
dotnet:mainfrom
Evangelink:evangelink/mstest-mtp-containerize-unit-tests
Open

Migrate containerize.UnitTests to MSTest.Sdk on MTP#54723
Evangelink wants to merge 12 commits into
dotnet:mainfrom
Evangelink:evangelink/mstest-mtp-containerize-unit-tests

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Follow-up to the pathfinder PR #54722 (which this stacks on).

containerize.UnitTests only uses xUnit Fact/Theory/InlineData/Assert APIs — it does not use any types from Microsoft.NET.TestFramework. So the project can drop its TestFramework ProjectReference and switch to MSTest.Sdk in one self-contained change.

Changes

  • test/containerize.UnitTests/containerize.UnitTests.csproj
  • test/containerize.UnitTests/ParserTests.cs: xUnit → MSTest mechanical conversion: [Fact]/[Theory][TestMethod], [InlineData][DataRow], add [TestClass], Assert.NotNull/Equal/Empty/SingleIsNotNull/AreEqual/IsEmpty/HasCount(1, ...).

Verification

9/9 tests pass on MTP (~400 ms).

Merge ordering

Depends on #54722. Once that merges, this PR will rebase cleanly onto main.

Relates to #52914.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR continues the test-suite migration to MSTest.Sdk on Microsoft.Testing.Platform (MTP) by opting specific test projects out of the repo-wide xUnit defaults and converting their tests/assertions accordingly, while also relocating Aspire integration coverage back into the xUnit-based dotnet-watch.Tests project.

Changes:

  • Switch containerize.UnitTests (and the stacked Aspire unit test project) to Sdk="MSTest.Sdk" + UseMSTestSdk=true, removing xUnit-coupled test framework references.
  • Mechanically convert affected test sources from xUnit attributes/asserts to MSTest equivalents.
  • Move Aspire integration tests/utilities into dotnet-watch.Tests and add the needed project reference + InternalsVisibleTo.
Show a summary per file
File Description
global.json Pins MSTest.Sdk under msbuild-sdks for Sdk resolution.
test/Directory.Build.targets Gates xUnit defaults/usings behind UseMSTestSdk != true.
test/containerize.UnitTests/containerize.UnitTests.csproj Migrates the project to MSTest.Sdk, opts out of xUnit defaults, drops Microsoft.NET.TestFramework reference.
test/containerize.UnitTests/ParserTests.cs Converts tests to MSTest attributes/asserts (one remaining xUnit assert needs fixing).
test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/Microsoft.DotNet.HotReload.Watch.Aspire.Tests.csproj Migrates Aspire unit test project to MSTest.Sdk, adds MSTest + assertion global usings, drops xUnit-coupled test utilities reference.
test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AssertEx.cs Adds local assertion helper to avoid dependency on xUnit-coupled shared utilities.
test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireServerLauncherCliTests.cs Converts xUnit tests to MSTest.
test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireResourceLauncherCliTests.cs Converts xUnit tests to MSTest (keeps assertion-library usage via Should() style).
test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireHostLauncherTests.cs Converts xUnit tests to MSTest.
test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireHostLauncherCliTests.cs Converts xUnit tests to MSTest.
test/dotnet-watch.Tests/dotnet-watch.Tests.csproj Adds Watch.Aspire project reference needed for moved Aspire integration tests.
test/dotnet-watch.Tests/Aspire/PipeUtilities.cs Adds a pipe helper for integration tests (missing using System.Text; needs fixing).
test/dotnet-watch.Tests/Aspire/AspireLauncherIntegrationTests.cs Renames test class to reflect integration scope.
src/Dotnet.Watch/Watch.Aspire/Properties/AssemblyInfo.cs Adds InternalsVisibleTo for dotnet-watch.Tests to access required internals.

Copilot's findings

  • Files reviewed: 13/14 changed files
  • Comments generated: 1

Comment thread test/containerize.UnitTests/ParserTests.cs
@Evangelink Evangelink marked this pull request as draft June 11, 2026 19:53
@Evangelink Evangelink force-pushed the evangelink/mstest-mtp-containerize-unit-tests branch from 580dad3 to b37a18b Compare June 11, 2026 20:06
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 11, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink Evangelink force-pushed the evangelink/mstest-mtp-containerize-unit-tests branch from b37a18b to e964809 Compare June 11, 2026 20:17
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 11, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 11, 2026
… on MTP

Same pattern as previous migrations. None of the 6 test files used any
Microsoft.NET.TestFramework types - only xUnit primitives - so the
TestFramework ProjectReference can be dropped and the project switched to
MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* 6 test files: xUnit -> MSTest mechanical conversion plus targeted fixes:
  - [Fact]/[Theory] -> [TestMethod], [InlineData] -> [DataRow], add [TestClass].
  - Assert.True/False/Null/NotNull/Empty/NotEmpty/Equal/NotEqual ->
    IsTrue/IsFalse/IsNull/IsNotNull/IsEmpty/IsNotEmpty/AreEqual/AreNotEqual.
  - Assert.Single(x) -> Assert.HasCount(1, x).
  - String Assert.Contains(needle, haystack) -> StringAssert.Contains(haystack, needle)
    (xUnit and MSTest argument orders are reversed).
  - One Assert.DoesNotContain(needle, str) -> Assert.IsFalse(str.Contains(needle)).
  - Assert.Collection in BrowserScriptMiddlewareTest expanded to inline
    Assert.HasCount + indexed AreEqual checks.
  - Assert.ThrowsAsync<T> -> Assert.ThrowsExactlyAsync<T>.
  - Assert.AreEqual on byte[]/int[] -> Assert.AreSequenceEqual (MSTEST0065:
    MSTest does not do element-wise equality on collections; the analyzer
    catches a real semantic difference vs xUnit).
  - StringValues (Microsoft.Extensions.Primitives) ambiguity with
    Assert.AreEqual<T> resolved by calling .ToString() at 5 call sites.
  - xUnit v3 TestContext.Current.CancellationToken -> CancellationToken.None
    (MSTest's TestContext.Current is experimental; tests do not actually
    require test-cancellation propagation).

Verification: 110/110 tests pass on MTP in ~480 ms.

Stacks on dotnet#54724 which stacks on dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
Member Author

Re-validated this PR against the new migrate-xunit-to-mstest skill landed in #54727 and bumped MSTest.Sdk to 4.3.0-preview.26311.10 (latest internal preview) via the pathfinder.

Changes applied in the latest push on this branch:
Assert.HasCount(1, parseResult.Errors) -> Assert.ContainsSingle(parseResult.Errors) (2 sites).

Other gotchas reviewed (no changes needed here):

  • Assert.AreEqual argument order — verified (expected, actual) throughout, matching the xUnit Assert.Equal(expected, actual) original.
  • CollectionAssert argument order — verified.
  • Assert.ThrowsExactly<T> vs Assert.Throws<T> semantics — verified (xUnit Throws<T> is exact; MSTest's same-named API is inclusive, so the migration uses ThrowsExactly<T>).
  • IsInstanceOfType<T> vs IsExactInstanceOfType<T> — see dotnet/skills#755 for the cheatsheet update we filed upstream.

Tests still pass locally on the bumped MSTest.Sdk.

@Evangelink Evangelink force-pushed the evangelink/mstest-mtp-containerize-unit-tests branch from e964809 to 914956a Compare June 11, 2026 20:33
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 11, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 11, 2026
… on MTP

Same pattern as previous migrations. None of the 6 test files used any
Microsoft.NET.TestFramework types - only xUnit primitives - so the
TestFramework ProjectReference can be dropped and the project switched to
MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* 6 test files: xUnit -> MSTest mechanical conversion plus targeted fixes:
  - [Fact]/[Theory] -> [TestMethod], [InlineData] -> [DataRow], add [TestClass].
  - Assert.True/False/Null/NotNull/Empty/NotEmpty/Equal/NotEqual ->
    IsTrue/IsFalse/IsNull/IsNotNull/IsEmpty/IsNotEmpty/AreEqual/AreNotEqual.
  - Assert.Single(x) -> Assert.HasCount(1, x).
  - String Assert.Contains(needle, haystack) -> StringAssert.Contains(haystack, needle)
    (xUnit and MSTest argument orders are reversed).
  - One Assert.DoesNotContain(needle, str) -> Assert.IsFalse(str.Contains(needle)).
  - Assert.Collection in BrowserScriptMiddlewareTest expanded to inline
    Assert.HasCount + indexed AreEqual checks.
  - Assert.ThrowsAsync<T> -> Assert.ThrowsExactlyAsync<T>.
  - Assert.AreEqual on byte[]/int[] -> Assert.AreSequenceEqual (MSTEST0065:
    MSTest does not do element-wise equality on collections; the analyzer
    catches a real semantic difference vs xUnit).
  - StringValues (Microsoft.Extensions.Primitives) ambiguity with
    Assert.AreEqual<T> resolved by calling .ToString() at 5 call sites.
  - xUnit v3 TestContext.Current.CancellationToken -> CancellationToken.None
    (MSTest's TestContext.Current is experimental; tests do not actually
    require test-cancellation propagation).

Verification: 110/110 tests pass on MTP in ~480 ms.

Stacks on dotnet#54724 which stacks on dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink Evangelink force-pushed the evangelink/mstest-mtp-containerize-unit-tests branch from 914956a to 865c83b Compare June 11, 2026 21:03
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 11, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 11, 2026
… on MTP

Same pattern as previous migrations. None of the 6 test files used any
Microsoft.NET.TestFramework types - only xUnit primitives - so the
TestFramework ProjectReference can be dropped and the project switched to
MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* 6 test files: xUnit -> MSTest mechanical conversion plus targeted fixes:
  - [Fact]/[Theory] -> [TestMethod], [InlineData] -> [DataRow], add [TestClass].
  - Assert.True/False/Null/NotNull/Empty/NotEmpty/Equal/NotEqual ->
    IsTrue/IsFalse/IsNull/IsNotNull/IsEmpty/IsNotEmpty/AreEqual/AreNotEqual.
  - Assert.Single(x) -> Assert.HasCount(1, x).
  - String Assert.Contains(needle, haystack) -> StringAssert.Contains(haystack, needle)
    (xUnit and MSTest argument orders are reversed).
  - One Assert.DoesNotContain(needle, str) -> Assert.IsFalse(str.Contains(needle)).
  - Assert.Collection in BrowserScriptMiddlewareTest expanded to inline
    Assert.HasCount + indexed AreEqual checks.
  - Assert.ThrowsAsync<T> -> Assert.ThrowsExactlyAsync<T>.
  - Assert.AreEqual on byte[]/int[] -> Assert.AreSequenceEqual (MSTEST0065:
    MSTest does not do element-wise equality on collections; the analyzer
    catches a real semantic difference vs xUnit).
  - StringValues (Microsoft.Extensions.Primitives) ambiguity with
    Assert.AreEqual<T> resolved by calling .ToString() at 5 call sites.
  - xUnit v3 TestContext.Current.CancellationToken -> CancellationToken.None
    (MSTest's TestContext.Current is experimental; tests do not actually
    require test-cancellation propagation).

Verification: 110/110 tests pass on MTP in ~480 ms.

Stacks on dotnet#54724 which stacks on dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit that referenced this pull request Jun 12, 2026
Imports the migrate-xunit-to-mstest skill from dotnet/skills@main
(plugins/dotnet-test/skills/migrate-xunit-to-mstest) into this repo so
the xUnit -> MSTest migration that's currently in progress (#54722,
#54723, #54724, #54725, #54726) has a documented, repeatable procedure
that contributors and agents can follow consistently.

Files added (verbatim from upstream):
- .github/skills/migrate-xunit-to-mstest/SKILL.md
- .github/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md

Note: SKILL.md is 546 lines, slightly above the 500-line "Progressive
Disclosure" guideline checked by .github/skills/ValidateSkill.cs. The
validator is advisory (not CI-enforced) and we are intentionally
mirroring the upstream content verbatim to keep future syncs trivial.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
Member Author

Replaced the manual <UseMSTestSdk>true</UseMSTestSdk> opt-in with the property MSTest.Sdk already sets for us: UsingMSTestSdk. Since MSTest.Sdk's Sdk.props runs before Microsoft.NET.Sdk.props and test/Directory.Build.targets is imported at the bottom of evaluation, the property is in scope wherever we need it — no per-project knob required.

Also refreshed the related comments in XUnitPublish.targets / XUnitRunner.targets and renamed the intermediate _UseMSTestSdk MSBuild property to _UsingMSTestSdk for clarity. (Thanks @Evangelink for the catch.)

@Evangelink

Copy link
Copy Markdown
Member Author

Made --report-trx conditional on Microsoft.Testing.Extensions.TrxReport actually being loaded. MSTest.Sdk enables that extension by default via EnableMicrosoftTestingExtensionsTrxReport=true for the Default / AllMicrosoft profiles, but other MTP hosts (xUnit v3 MTP, MSTest.Sdk with TestingExtensionsProfile=None, etc.) do not — passing --report-trx there fails with 'unknown argument'.

The new GetTrxReportEnabled target queries that property; XUnitRunner.targets propagates it as EnableTrxReport metadata, and SDKCustomCreateXUnitWorkItemsWithTestExclusion only emits the flag when it's true. No behavioural change for the current PRs since all migrated projects are MSTest.Sdk-based, but the dispatcher is now forward-safe.

(Applied to all 9 stacked PRs since they share these plumbing files.)

@Evangelink

Copy link
Copy Markdown
Member Author

Replaced the custom <UseMSTestSdk> opt-in property with the built-in UsingMSTestSdk property that MSTest.Sdk already sets in its Sdk.props before Directory.Build.props is evaluated. This drops a redundant declaration in every migrated csproj and just reads what the SDK already publishes.

@Evangelink

Copy link
Copy Markdown
Member Author

Also removed <IsPackable>false</IsPackable> from the migrated csproj — MSTest.Sdk's Runner/Common.targets already sets it, so the per-project declaration is redundant.

@Evangelink

Copy link
Copy Markdown
Member Author

Round 3: moved FluentAssertions Using and AwesomeAssertions PackageReference to test/Directory.Build.targets.

The Using is now global for any test project ('$(IsTestProject)' == 'true' OR '$(UsingMSTestSdk)' == 'true'). The PackageReference is added for MSTest.Sdk projects only — xUnit projects already get it transitively via the Microsoft.NET.TestFramework project reference.

Deviation from your literal suggestion: I left the Microsoft.NET.TestFramework.* Usings and Xunit Using gated on UsingMSTestSdk != true. Moving them unconditional would also require a global <ProjectReference Include="Microsoft.NET.TestFramework" /> (otherwise MSTest projects would fail with CS0246), which would drag xunit.v3.assert and other xUnit pieces into the MSTest projects. Happy to apply the broader change (with a global ProjectRef) if you'd prefer.

@Evangelink Evangelink marked this pull request as ready for review June 12, 2026 15:10
Evangelink and others added 7 commits June 12, 2026 18:03
…n MTP

This is a pathfinder PR for migrating the test suite to MSTest on
Microsoft.Testing.Platform (MTP). Microsoft.DotNet.HotReload.Watch.Aspire.Tests
was chosen because it has no dependency on the shared Microsoft.NET.TestFramework
(which is xUnit-coupled and referenced by ~57 of 78 test projects), so it can
migrate in isolation without unblocking dependents first.

Changes:

* global.json: add MSTest.Sdk 4.3.0-preview.26307.5 to msbuild-sdks.
* test/Directory.Build.targets: gate the xUnit defaults
  (TestRunnerName=XUnitV3, Using Include=Xunit, etc.) behind
  $(UseMSTestSdk) != true, so MSTest.Sdk projects opt out cleanly.
* test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests:
  - csproj now uses Sdk="MSTest.Sdk", sets UseMSTestSdk=true, references
    AwesomeAssertions and only the Watch.Aspire project. MTP is on by default
    via MSTest.Sdk (EnableMSTestRunner + TestingPlatformDotnetTestSupport).
  - All 4 unit-test files converted from xUnit to MSTest attributes/asserts
    ([Fact]/[Theory] -> [TestMethod]/[DataRow], Assert.* equivalents,
    Assert.IsInstanceOfType<T>, Assert.HasCount, Assert.IsEmpty).
  - Local AssertEx.SequenceEqual<T> helper replaces the xUnit-coupled one
    from HotReload.Test.Utilities.
* Move the 2 integration tests (AspireLauncherTests + PipeUtilities) to
  test/dotnet-watch.Tests/Aspire/ so the Aspire.Tests project stays a pure
  MSTest unit-test project. They keep xUnit because they depend on
  WatchSdkTest, WatchableApp, [PlatformSpecificFact], ITestOutputHelper and
  TestAssets from Microsoft.NET.TestFramework. AspireLauncherTests was
  renamed to AspireLauncherIntegrationTests to reflect its new role.
* src/Dotnet.Watch/Watch.Aspire/Properties/AssemblyInfo.cs: grant
  InternalsVisibleTo to dotnet-watch.Tests (needed by PipeUtilities, which
  uses internal WatchStatusEvent).
* test/dotnet-watch.Tests/dotnet-watch.Tests.csproj: add ProjectReference to
  Watch.Aspire (ExcludeAssets=Runtime) so the moved integration tests
  compile.

Verification:
* Microsoft.DotNet.HotReload.Watch.Aspire.Tests builds with MSTest.Sdk and
  all 58 unit tests pass under MTP (705 ms).
* test/dotnet-watch.Tests builds successfully with the moved files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Bumps MSTest.Sdk to the latest internal preview to pick up the newest
  4.3 assertion APIs (Assert.ContainsSingle, Assert.Contains for strings
  with the more natural (needle, haystack) signature, etc.).
- Applies the assertion mapping flagged by the migrate-xunit-to-mstest
  skill in this repo (.github/skills/migrate-xunit-to-mstest, PR dotnet#54727):
    Assert.HasCount(1, x) -> Assert.ContainsSingle(x)
  (one occurrence in AspireResourceLauncherCliTests.cs)

Verified: 58/58 tests still pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…parity

Per reviewer feedback: MSTest 4.1.0+ exposes Assert.IsExactInstanceOfType<T>(value)
which returns T and enforces exact-type semantics -- the proper equivalent
of xUnit's Assert.IsType<T>(x). Assert.IsInstanceOfType<T> is the equivalent
of xUnit's Assert.IsAssignableFrom<T> (assignable, not exact), which would
be a silent semantic regression for the IsType<T> originals.

All 39 occurrences across AspireHostLauncherCliTests.cs,
AspireResourceLauncherCliTests.cs, AspireServerLauncherCliTests.cs, and
AspireLauncherIntegrationTests.cs were originally Assert.IsType<T> in
xUnit (verified against main), so all 39 are flipped to
Assert.IsExactInstanceOfType<T>.

Note: the migrate-xunit-to-mstest skill cheatsheet at
.github/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md
recommends `Assert.IsInstanceOfType<T>` plus an extra typeof-check for
exact-type semantics; that guidance predates IsExactInstanceOfType being
available. Follow-up upstream (dotnet/skills) suggested.

Verified: 58/58 Aspire tests still pass; dotnet-watch.Tests builds clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MSTest.Sdk already adds this as an implicit global using.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MSTest 4.3+ provides Assert.AreSequenceEqual for element-wise IEnumerable<T> compare with a nice diff message, so the project-local AssertEx helper is no longer needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…est/Directory.Build.targets

Per @Evangelink: keep per-csproj boilerplate minimal. FluentAssertions is now a
global using for any test project (gated on IsTestProject OR UsingMSTestSdk),
and AwesomeAssertions is added as a PackageReference for MSTest.Sdk projects.
xUnit projects continue to pick it up transitively via Microsoft.NET.TestFramework.

The Microsoft.NET.TestFramework.* and Xunit usings remain gated on the xUnit
branch (UsingMSTestSdk != true) because MSTest projects in this repo do not
reference Microsoft.NET.TestFramework; making those usings global would fail
with CS0246.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The recent `Helix dispatcher: gate --report-trx on TrxReport extension
being loaded` commit accidentally removed the ProjectReference to
Microsoft.DotNet.HotReload.Watch.Aspire from dotnet-watch.Tests.csproj
(introduced in the `Migrate Microsoft.DotNet.HotReload.Watch.Aspire.Tests
to MSTest.Sdk on MTP` commit to allow the moved AspireLauncherIntegrationTests
and PipeUtilities to compile).

Without that reference, the build fails with:

    error CS0246: The type or namespace name 'WatchStatusEvent' could not be
    found (are you missing a using directive or an assembly reference?)
    [test/dotnet-watch.Tests/Aspire/PipeUtilities.cs]

Re-add the ProjectReference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink Evangelink force-pushed the evangelink/mstest-mtp-containerize-unit-tests branch from 656097c to fe30f09 Compare June 12, 2026 16:08
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 12, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 12, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 12, 2026
… on MTP

Same pattern as previous migrations. None of the 6 test files used any
Microsoft.NET.TestFramework types - only xUnit primitives - so the
TestFramework ProjectReference can be dropped and the project switched to
MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* 6 test files: xUnit -> MSTest mechanical conversion plus targeted fixes:
  - [Fact]/[Theory] -> [TestMethod], [InlineData] -> [DataRow], add [TestClass].
  - Assert.True/False/Null/NotNull/Empty/NotEmpty/Equal/NotEqual ->
    IsTrue/IsFalse/IsNull/IsNotNull/IsEmpty/IsNotEmpty/AreEqual/AreNotEqual.
  - Assert.Single(x) -> Assert.HasCount(1, x).
  - String Assert.Contains(needle, haystack) -> StringAssert.Contains(haystack, needle)
    (xUnit and MSTest argument orders are reversed).
  - One Assert.DoesNotContain(needle, str) -> Assert.IsFalse(str.Contains(needle)).
  - Assert.Collection in BrowserScriptMiddlewareTest expanded to inline
    Assert.HasCount + indexed AreEqual checks.
  - Assert.ThrowsAsync<T> -> Assert.ThrowsExactlyAsync<T>.
  - Assert.AreEqual on byte[]/int[] -> Assert.AreSequenceEqual (MSTEST0065:
    MSTest does not do element-wise equality on collections; the analyzer
    catches a real semantic difference vs xUnit).
  - StringValues (Microsoft.Extensions.Primitives) ambiguity with
    Assert.AreEqual<T> resolved by calling .ToString() at 5 call sites.
  - xUnit v3 TestContext.Current.CancellationToken -> CancellationToken.None
    (MSTest's TestContext.Current is experimental; tests do not actually
    require test-cancellation propagation).

Verification: 110/110 tests pass on MTP in ~480 ms.

Stacks on dotnet#54724 which stacks on dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 12, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 12, 2026
… on MTP

Same pattern as previous migrations. None of the 6 test files used any
Microsoft.NET.TestFramework types - only xUnit primitives - so the
TestFramework ProjectReference can be dropped and the project switched to
MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* 6 test files: xUnit -> MSTest mechanical conversion plus targeted fixes:
  - [Fact]/[Theory] -> [TestMethod], [InlineData] -> [DataRow], add [TestClass].
  - Assert.True/False/Null/NotNull/Empty/NotEmpty/Equal/NotEqual ->
    IsTrue/IsFalse/IsNull/IsNotNull/IsEmpty/IsNotEmpty/AreEqual/AreNotEqual.
  - Assert.Single(x) -> Assert.HasCount(1, x).
  - String Assert.Contains(needle, haystack) -> StringAssert.Contains(haystack, needle)
    (xUnit and MSTest argument orders are reversed).
  - One Assert.DoesNotContain(needle, str) -> Assert.IsFalse(str.Contains(needle)).
  - Assert.Collection in BrowserScriptMiddlewareTest expanded to inline
    Assert.HasCount + indexed AreEqual checks.
  - Assert.ThrowsAsync<T> -> Assert.ThrowsExactlyAsync<T>.
  - Assert.AreEqual on byte[]/int[] -> Assert.AreSequenceEqual (MSTEST0065:
    MSTest does not do element-wise equality on collections; the analyzer
    catches a real semantic difference vs xUnit).
  - StringValues (Microsoft.Extensions.Primitives) ambiguity with
    Assert.AreEqual<T> resolved by calling .ToString() at 5 call sites.
  - xUnit v3 TestContext.Current.CancellationToken -> CancellationToken.None
    (MSTest's TestContext.Current is experimental; tests do not actually
    require test-cancellation propagation).

Verification: 110/110 tests pass on MTP in ~480 ms.

Stacks on dotnet#54724 which stacks on dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink and others added 5 commits June 12, 2026 18:29
Introduces an MSTest-flavored counterpart to the xUnit-based
Microsoft.DotNet.HotReload.Test.Utilities so that test helpers that
need MSTest's TestContext (e.g. TestLogger, TestLoggerFactory) can be
shared across MSTest.Sdk test projects instead of being copy-pasted
per project.

This commit also migrates the inline TestLogger from
Microsoft.DotNet.HotReload.Client.Tests to consume the shared project,
which serves as the first reference consumer. Subsequent migration PRs
(DeltaApplier.Tests, Containers.UnitTests) will adopt the same project
reference instead of adding their own TestLogger/TestLoggerFactory copies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Follow-up to the pathfinder migration. containerize.UnitTests only uses xUnit
Fact/Theory/InlineData/Assert APIs - it does not use any types from
Microsoft.NET.TestFramework. So the project can drop its TestFramework
ProjectReference and switch to MSTest.Sdk in one self-contained PR.

Changes:
* test/containerize.UnitTests/containerize.UnitTests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true (opts the project out of the
    xUnit defaults in test/Directory.Build.targets - gate introduced in PR dotnet#54722).
  - Drop the ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/containerize.UnitTests/ParserTests.cs: xUnit -> MSTest mechanical
  conversion: [Fact]/[Theory] -> [TestMethod], [InlineData] -> [DataRow],
  add [TestClass], Assert.NotNull/Equal/Empty/Single ->
  IsNotNull/AreEqual/IsEmpty/HasCount(1, ...).

Verification: 9/9 tests pass on MTP in ~400 ms.

Stacks on top of PR dotnet#54722 (pathfinder). Merge after that one.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…le(x)

Applies the assertion mapping flagged by the migrate-xunit-to-mstest skill
(.github/skills/migrate-xunit-to-mstest, PR dotnet#54727). Two occurrences in
ParserTests.cs converted from `Assert.HasCount(1, parseResult.Errors)` to
the more idiomatic `Assert.ContainsSingle(parseResult.Errors)`, which
matches the xUnit original (`Assert.Single`) more directly.

Verified: 9/9 tests still pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MSTest.Sdk already adds this as an implicit global using.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MSTest.Sdk's Runner/Common.targets already sets `<IsPackable>false</IsPackable>`
for every MSTest.Sdk project, so the per-project declaration is redundant.
@Evangelink Evangelink force-pushed the evangelink/mstest-mtp-containerize-unit-tests branch from fe30f09 to 439fef5 Compare June 12, 2026 16:36
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 12, 2026
Same pattern as containerize.UnitTests (dotnet#54723). This project's single test
file only uses xUnit Fact/Assert.Equal - no Microsoft.NET.TestFramework
types - so the TestFramework ProjectReference can be dropped and the
project switched to MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.DotNet.ApiCompat.Tests/Microsoft.DotNet.ApiCompat.Tests.csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* test/Microsoft.DotNet.ApiCompat.Tests/RegexStringTransformerTests.cs:
  [Fact] -> [TestMethod], add [TestClass], Assert.Equal -> Assert.AreEqual.

Verification: 5/5 tests pass on MTP in ~250 ms.

Stacks on top of dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evangelink added a commit to Evangelink/sdk that referenced this pull request Jun 12, 2026
… on MTP

Same pattern as previous migrations. None of the 6 test files used any
Microsoft.NET.TestFramework types - only xUnit primitives - so the
TestFramework ProjectReference can be dropped and the project switched to
MSTest.Sdk in one self-contained change.

Changes:
* test/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/csproj:
  - Use Sdk="MSTest.Sdk", set UseMSTestSdk=true.
  - Drop ProjectReference to Microsoft.NET.TestFramework (unused).
  - Drop OutputType=Exe (MSTest.Sdk handles it).
  - Add Microsoft.VisualStudio.TestTools.UnitTesting global using.
* 6 test files: xUnit -> MSTest mechanical conversion plus targeted fixes:
  - [Fact]/[Theory] -> [TestMethod], [InlineData] -> [DataRow], add [TestClass].
  - Assert.True/False/Null/NotNull/Empty/NotEmpty/Equal/NotEqual ->
    IsTrue/IsFalse/IsNull/IsNotNull/IsEmpty/IsNotEmpty/AreEqual/AreNotEqual.
  - Assert.Single(x) -> Assert.HasCount(1, x).
  - String Assert.Contains(needle, haystack) -> StringAssert.Contains(haystack, needle)
    (xUnit and MSTest argument orders are reversed).
  - One Assert.DoesNotContain(needle, str) -> Assert.IsFalse(str.Contains(needle)).
  - Assert.Collection in BrowserScriptMiddlewareTest expanded to inline
    Assert.HasCount + indexed AreEqual checks.
  - Assert.ThrowsAsync<T> -> Assert.ThrowsExactlyAsync<T>.
  - Assert.AreEqual on byte[]/int[] -> Assert.AreSequenceEqual (MSTEST0065:
    MSTest does not do element-wise equality on collections; the analyzer
    catches a real semantic difference vs xUnit).
  - StringValues (Microsoft.Extensions.Primitives) ambiguity with
    Assert.AreEqual<T> resolved by calling .ToString() at 5 call sites.
  - xUnit v3 TestContext.Current.CancellationToken -> CancellationToken.None
    (MSTest's TestContext.Current is experimental; tests do not actually
    require test-cancellation propagation).

Verification: 110/110 tests pass on MTP in ~480 ms.

Stacks on dotnet#54724 which stacks on dotnet#54723 which stacks on dotnet#54722.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
Member Author

/azp run dotnet-sdk-public-ci

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@Evangelink

Copy link
Copy Markdown
Member Author

/azp run dotnet-sdk-public-ci

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants