Skip to content

Clean up xUnit from the SDK test harness#55059

Merged
Evangelink merged 5 commits into
mainfrom
dev/amauryleve/test-xunit-cleanup
Jun 30, 2026
Merged

Clean up xUnit from the SDK test harness#55059
Evangelink merged 5 commits into
mainfrom
dev/amauryleve/test-xunit-cleanup

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

Follow-up cleanup after the bulk test migration to MSTest.Sdk on MTP (#54976). This removes xUnit from the SDK-owned test harness as far as is responsibly possible and factors out repeated test-project boilerplate. Reviewable as three self-contained commits.

1. Centralize Microsoft.NET.TestFramework global usings

The five Microsoft.NET.TestFramework.* namespaces were declared as <Using> items in ~34 test .csproj files (and three GlobalUsings.cs). Replaced with a single ProjectReference-driven ItemGroup in test/Directory.Build.targets that applies them to any project referencing the SDK test framework (legacy or .MSTest). The two framework projects keep their own local usings.

2. Migrate the last SDK-owned xUnit helper + stop Arcade's xUnit injection

  • Microsoft.DotNet.HotReload.Test.Utilities (xUnit v3) → MSTest: Xunit.Assert/XunitException/NotEqualException → MSTest Assert/AssertFailedException; ITestOutputHelper bound to Microsoft.NET.TestFramework; deleted the unused WatchSdkTest; now references Microsoft.NET.TestFramework.MSTest and drops xunit.v3.extensibility.core + Xunit.Combinatorial.
  • dotnet-watch.Tests (its only consumer) drops its xunit.v3.* packages; DualOutputHelper no longer bridges Xunit.ITestOutputHelper. The .MSTest reference is exposed as global,MSTestFramework so previously-aliased types still resolve once the legacy framework stops leaking in transitively.
  • Set UsingToolXUnit=false for MSTest.Sdk projects so Arcade stops injecting the unused xUnit v2 package set (xunit.core/assert/runner.console/runner.visualstudio) into every MSTest test output — those projects run on Microsoft.Testing.Platform.

3. Drop the legacy xUnit framework from SDK-owned consumers

ComponentMocks and Msbuild.Tests.Utilities use no xUnit and no framework types directly, so they're repointed from the legacy (xUnit v3) Microsoft.NET.TestFramework to .MSTest. With ComponentMocks no longer compiled against the legacy framework, dotnet.Tests and Microsoft.DotNet.PackageInstall.Tests drop their legacy ProjectReference and the RemoveConflictingTestFrameworkReference (CS0433) workaround.

Validation

All touched projects build 0 warnings / 0 errors against the locally-built SDK. Representative MTP runs pass: dotnet-watch.Tests 35/35, PackageInstall.Tests/ToolPackageDownloaderTests 50 passed + 2 skipped (heavy ComponentMocks users), dotnet.Tests/LaunchSettingsParserTests 9/9. Verified no xUnit assemblies are deployed in the migrated outputs.

Intentionally out of scope

Literal "zero xUnit" isn't reachable from this repo; the following are left untouched and still pull in xUnit:

  • Legacy Microsoft.NET.TestFramework — now referenced only by the vendored Microsoft.CodeAnalysis.NetAnalyzers tests (Roslyn mirror) and the dotnet/templating-owned Microsoft.TemplateEngine.Cli.UnitTests.
  • dotnet/templating-owned Microsoft.TemplateEngine.Mocks / TestHelper (xunit.v3.extensibility.core) and dotnet-new.IntegrationTests' runtime-only Verify.XunitV3 — per AGENTS.md, templating changes belong in dotnet/templating.
  • eng/XUnitV3, test/xunit.runner.json, test/xunit-runner — still drive the remaining xUnit v3 projects above.
  • The shipping XUnit-CSharp project template and the xUnit test-asset fixtures (deliberately xUnit).

Once the vendored NetAnalyzers tests and the templating-owned helpers move off xUnit, the legacy Microsoft.NET.TestFramework can be deleted and …MSTest renamed to take its place.

Evangelink and others added 3 commits June 29, 2026 22:18
…y.Build.targets

Replace the per-project <Using Include="Microsoft.NET.TestFramework.*" /> blocks
(repeated across ~34 test projects, plus three GlobalUsings.cs files) with a single
ProjectReference-driven ItemGroup in test/Directory.Build.targets that applies the five
framework namespaces to any project referencing the SDK test framework (the legacy
Microsoft.NET.TestFramework or its MSTest counterpart). The two framework projects
themselves reference neither and keep their own local usings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…MSTest projects out of Arcade's xUnit

Migrate Microsoft.DotNet.HotReload.Test.Utilities (the last SDK-owned xUnit v3 test
helper) to MSTest: map Xunit.Assert/XunitException/NotEqualException to MSTest
Assert/AssertFailedException, bind ITestOutputHelper to Microsoft.NET.TestFramework,
delete the unused WatchSdkTest, and reference Microsoft.NET.TestFramework.MSTest instead
of the legacy framework (dropping xunit.v3.extensibility.core + Xunit.Combinatorial).

dotnet-watch.Tests, its only consumer, then drops its xunit.v3 package references and
its DualOutputHelper no longer needs to bridge Xunit.ITestOutputHelper. With the legacy
framework no longer leaking in transitively, the Microsoft.NET.TestFramework.MSTest
reference is exposed as global,MSTestFramework so the previously-aliased types resolve.

Separately, set UsingToolXUnit=false for MSTest.Sdk projects so Arcade stops injecting the
unused xUnit v2 package set (xunit.core/assert/runner.console/runner.visualstudio) into
every MSTest test output; MSTest projects run on Microsoft.Testing.Platform.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ComponentMocks and Msbuild.Tests.Utilities use no xUnit and no framework types directly,
so repoint them from the legacy (xUnit v3) Microsoft.NET.TestFramework to the MSTest
counterpart. With ComponentMocks no longer compiled against the legacy framework,
dotnet.Tests and Microsoft.DotNet.PackageInstall.Tests can drop their legacy framework
ProjectReference and the RemoveConflictingTestFrameworkReference (CS0433) workaround.

This removes the legacy framework / xUnit v3 from all of these projects. The legacy
framework now remains referenced only by the vendored NetAnalyzers tests and the
dotnet/templating-owned Microsoft.TemplateEngine.Cli.UnitTests, both out of scope here.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The vendored Microsoft.CodeAnalysis.NetAnalyzers.UnitTests imports
test/Directory.Build.targets and is an xUnit (non-MSTest) test project that
relied on the global Xunit using the centralization commit dropped, breaking
compilation with CS0246 (Fact/Theory not found). Re-add the Xunit using under
the IsTestProject and non-MSTest condition (MSTest projects must not get it, as
it clashes with MSTest's Assert).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink Evangelink marked this pull request as ready for review June 30, 2026 08:39
Copilot AI review requested due to automatic review settings June 30, 2026 08:39
@Evangelink Evangelink requested review from a team and tmat as code owners June 30, 2026 08:39
@Evangelink Evangelink enabled auto-merge June 30, 2026 08:39

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

Removes remaining xUnit dependencies from the SDK-owned test harness by centralizing Microsoft.NET.TestFramework* global usings, migrating the last SDK-owned xUnit-coupled helper library to MSTest, and preventing Arcade tooling from injecting unused xUnit v2 packages into MSTest.Sdk test outputs.

Changes:

  • Centralize Microsoft.NET.TestFramework* global usings in test/Directory.Build.targets based on ProjectReference detection, and remove duplicated per-project <Using> items / GlobalUsings.cs files.
  • Migrate Microsoft.DotNet.HotReload.Test.Utilities and dotnet-watch.Tests off xUnit v3 types/packages (assertions + output helper bridging).
  • Drop remaining SDK-owned consumers of the legacy xUnit-coupled Microsoft.NET.TestFramework and remove now-unneeded CS0433 workaround targets; opt MSTest.Sdk projects out of Arcade’s xUnit tooling injection.
Show a summary per file
File Description
test/trustedroots.Tests/trustedroots.Tests.csproj Remove redundant Microsoft.NET.TestFramework <Using> now provided centrally.
test/sdk-tasks.Tests/sdk-tasks.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj Switch from legacy Microsoft.NET.TestFramework to .MSTest reference.
test/msbuild.Integration.Tests/msbuild.Integration.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.Win32.Msi.Tests/Microsoft.Win32.Msi.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.WebTools.AspireService.Tests/Microsoft.WebTools.AspireService.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.TemplateEngine.Cli.UnitTests/GlobalUsings.cs Remove now-unnecessary Microsoft.NET.TestFramework* global usings.
test/Microsoft.NET.ToolPack.Tests/GlobalUsings.cs Delete per-project global usings file now covered by centralized usings.
test/Microsoft.NET.Sdk.Razor.Tests/Microsoft.NET.Sdk.Razor.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Sdk.BlazorWebAssembly.AoT.Tests/Microsoft.NET.Sdk.BlazorWebAssembly.AoT.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Restore.Tests/Microsoft.NET.Restore.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Rebuild.Tests/Microsoft.NET.Rebuild.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Publish.Tests/Microsoft.NET.Publish.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Pack.Tests/Microsoft.NET.Pack.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Clean.Tests/Microsoft.NET.Clean.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.NET.Build.Tests/GlobalUsings.cs Delete per-project global usings file now covered by centralized usings.
test/Microsoft.NET.Build.Tasks.Tests/Microsoft.NET.Build.Tasks.Tests.csproj Remove redundant Microsoft.NET.TestFramework <Using> item.
test/Microsoft.NET.Build.Extensions.Tasks.Tests/Microsoft.NET.Build.Extensions.Tasks.Tests.csproj Remove redundant Microsoft.NET.TestFramework <Using> item.
test/Microsoft.NET.Build.Containers.IntegrationTests/Microsoft.NET.Build.Containers.IntegrationTests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.DotNet.Tools.Tests.ComponentMocks/Microsoft.DotNet.Tools.Tests.ComponentMocks.csproj Switch from legacy Microsoft.NET.TestFramework to .MSTest reference.
test/Microsoft.DotNet.TemplateLocator.Tests/Microsoft.DotNet.TemplateLocator.Tests.csproj Remove redundant Microsoft.NET.TestFramework <Using> item.
test/Microsoft.DotNet.PackageValidation.Tests/Microsoft.DotNet.PackageValidation.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.DotNet.PackageInstall.Tests/Microsoft.DotNet.PackageInstall.Tests.csproj Remove legacy framework reference + CS0433 workaround target + redundant usings.
test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj Remove redundant Microsoft.NET.TestFramework <Using> item.
test/Microsoft.DotNet.HotReload.Test.Utilities/WatchSdkTest.cs Remove unused xUnit-based helper base class.
test/Microsoft.DotNet.HotReload.Test.Utilities/WatchableApp.cs Replace xUnit assertions with MSTest assertions.
test/Microsoft.DotNet.HotReload.Test.Utilities/TestLogger.cs Switch output helper type dependency away from xUnit.
test/Microsoft.DotNet.HotReload.Test.Utilities/Microsoft.DotNet.HotReload.Test.Utilities.csproj Switch test framework reference to .MSTest and drop xUnit v3 package refs.
test/Microsoft.DotNet.HotReload.Test.Utilities/DebugTestOutputLogger.cs Switch output helper interface to Microsoft.NET.TestFramework’s.
test/Microsoft.DotNet.HotReload.Test.Utilities/AwaitableProcess.cs Replace xUnit assertions with MSTest assertions.
test/Microsoft.DotNet.HotReload.Test.Utilities/AssertEx.cs Replace xUnit exception types with MSTest assertion failure.
test/Microsoft.DotNet.GenAPI.IntegrationTests/Microsoft.DotNet.GenAPI.IntegrationTests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.DotNet.Cli.Utils.Tests/Microsoft.DotNet.Cli.Utils.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.DotNet.ApiSymbolExtensions.Tests/Microsoft.DotNet.ApiSymbolExtensions.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.DotNet.ApiDiff.IntegrationTests/Microsoft.DotNet.ApiDiff.IntegrationTests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.DotNet.ApiCompatibility.Tests/Microsoft.DotNet.ApiCompatibility.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Microsoft.DotNet.ApiCompat.IntegrationTests/Microsoft.DotNet.ApiCompat.IntegrationTests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/EndToEnd.Tests/EndToEnd.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/dotnet.Tests/dotnet.Tests.csproj Remove legacy framework workaround and per-project Microsoft.NET.TestFramework* usings.
test/dotnet-watch.Tests/TestUtilities/DualOutputHelper.cs Remove xUnit output helper bridging; keep MSTest framework adapter.
test/dotnet-watch.Tests/dotnet-watch.Tests.csproj Drop per-project test framework usings and xUnit v3 runtime package refs; adjust aliasing.
test/dotnet-new.IntegrationTests/dotnet-new.IntegrationTests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items; keep xUnit-using removals.
test/dotnet-MsiInstallation.Tests/dotnet-MsiInstallation.Tests.csproj Remove redundant Windows-only Microsoft.NET.TestFramework* <Using> items.
test/dotnet-format.UnitTests/dotnet-format.UnitTests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/dotnet-aot.Tests/dotnet-aot.Tests.csproj Remove redundant Microsoft.NET.TestFramework* <Using> items.
test/Directory.Build.targets Add ProjectReference-driven global usings for Microsoft.NET.TestFramework*; keep xUnit global using limited to non-MSTest.Sdk projects.
test/Directory.Build.props Set UsingToolXUnit=false for MSTest.Sdk projects to stop Arcade xUnit v2 injection.
test/ArgumentForwarding.Tests/ArgumentForwarding.Tests.csproj Remove redundant Microsoft.NET.TestFramework <Using> item.

Copilot's findings

  • Files reviewed: 49/49 changed files
  • Comments generated: 1

Comment thread test/Microsoft.DotNet.HotReload.Test.Utilities/AssertEx.cs Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
Member Author

/ba-g #51530

@Evangelink Evangelink disabled auto-merge June 30, 2026 13:38
@Evangelink Evangelink merged commit 9465d33 into main Jun 30, 2026
26 of 28 checks passed
@Evangelink Evangelink deleted the dev/amauryleve/test-xunit-cleanup branch June 30, 2026 17:00
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 11.0-preview7 milestone Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants