Skip to content

Move libraries tests to xunit3#126277

Draft
Copilot wants to merge 61 commits intomainfrom
copilot/update-runtime-governance-docs
Draft

Move libraries tests to xunit3#126277
Copilot wants to merge 61 commits intomainfrom
copilot/update-runtime-governance-docs

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 29, 2026

Note

This PR was created with the assistance of GitHub Copilot.

This PR ports the test-only content from #125019 — moving libraries tests from xunit v2 to xunit v3. Production code is intentionally left unchanged.

Description

Key changes include:

  • xunit v3 package updates (eng/Versions.props, eng/testing/xunit/): Updates xunit dependencies from v2 to v3 packages
  • Build infrastructure (Directory.Build.targets, eng/testing/): Adds UseAppHost overrides and build validation for xunit v3 test projects
  • NuGet source (NuGet.config): Adds nuget.org feed for xunit v3 packages
  • Test runner updates (eng/testing/RunnerTemplate.sh, eng/testing/RunnerTemplate.cmd): Updates test execution to use xunit v3 runner
  • Test infrastructure (src/libraries/sendtohelix-browser.targets, src/libraries/sendtohelix-wasi.targets): Updates xunit trait filter syntax (-notrait-trait-) for xunit v3 compatibility
  • SingleFileTestRunner (src/libraries/Common/tests/SingleFileTestRunner/SingleFileTestRunner.cs): Updates for xunit v3 in-process runner APIs with AssemblyMetadata(3, ...) for NativeAOT compatibility
  • NativeAOT single-file targets (eng/testing/tests.singlefile.targets): Disables xunit auto-generated entry point for NativeAOT tests (uses SingleFileTestRunner instead)
  • Test code migrations (~640 test files): Updates test patterns for xunit v3 compatibility including:
    • TheoryData → typed TheoryData<T> with .Data accessor
    • IAsyncLifetime adjustments
    • Assert.ThrowsAsync pattern updates
    • Collection/class fixture changes
    • Skip mechanism updates (throw SkipTestExceptionAssert.SkipUnless/Assert.SkipWhen/Assert.Skip)
  • De Morgan's law skip condition fixes (6 total across 5 files): Fixed inverted skip conditions where compound negated if conditions were incorrectly converted to Assert.SkipUnless/Assert.SkipWhen without properly applying De Morgan's law:
    • HttpClientHandlerTest.Authentication.cs: if (!A || !B) throw SkipAssert.SkipUnless(A && B) (was incorrectly A || !B)
    • HttpClientHandlerTest.Headers.cs: if (!A && B) throw SkipAssert.SkipWhen(!A && B) (was incorrectly Assert.SkipUnless(A && B))
    • TextWriterTests.cs (2 instances): if (!A && !B) throw SkipAssert.SkipUnless(A || B) (was incorrectly A && !B)
    • BoundedChannelTests.cs: if (!A && !B) throw SkipAssert.SkipUnless(A || B) (was incorrectly A && !B)
    • RendezvousChannelTests.cs: if (!A && !B) throw SkipAssert.SkipUnless(A || B) (was incorrectly A && !B)
  • Documentation (docs/workflow/testing/libraries/xunit3-migration.md): Adds migration guide for common xunit v2→v3 patterns

All changes to production/source code (coreclr JIT, nativeaot CoreLib, System.Text.RegularExpressions, native libs, AndroidAppBuilder) have been reverted per reviewer feedback. Only test code, test infrastructure, and documentation changes remain.

See #125019 for full context and discussion.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Port of #125019

Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
@dotnet-policy-service dotnet-policy-service Bot added the linkable-framework Issues associated with delivering a linker friendly framework label Mar 29, 2026
The merge from upstream/main reintroduced xunit v2 patterns in files that
were modified on both branches:

- EdgeCaseTests.cs: [ConditionalTheory] -> [Theory] (fixes CS0618 build
  error blocking 21 CI jobs), SkipTestException -> SkipException.ForSkip()
- Regex.Match.Tests.cs: SkipTestException -> SkipException.ForSkip()
- DumpTestBase.cs: SkipTestException -> SkipException.ForSkip()

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

This comment has been minimized.

@agocke
Copy link
Copy Markdown
Member

agocke commented Mar 29, 2026

@copilot please revert all changes to production code

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/366384e9-ee01-45a6-8bc0-e3ec75e0d12d

Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 29, 2026

@copilot please revert all changes to production code

Reverted all 19 production code files to their original state in 7167df8. Files reverted:

  • src/coreclr/jit/codegenwasm.cpp, regallocwasm.cpp
  • src/coreclr/nativeaot/System.Private.CoreLib/src/.../ThunkedApis.cs
  • src/libraries/System.Text.RegularExpressions/src/... (3 files)
  • src/native/libs/... (9 files: JavaScript loader, CMakeLists, pal_*.c/.h/.m)
  • src/tasks/AndroidAppBuilder/Templates/monodroid-nativeaot.cs
  • src/libraries/sendtohelix-browser.targets, sendtohelix-wasi.targets

Only test code, test infrastructure (eng/testing/, Directory.Build.targets, NuGet.config, eng/Versions.props), and documentation changes remain.

@agocke
Copy link
Copy Markdown
Member

agocke commented Mar 29, 2026

@copilot these changes are test infra: src/libraries/sendtohelix-browser.targets, sendtohelix-wasi.targets

…-wasi.targets (test infra)

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/257c3fec-6b69-4b38-b147-c12d2df91422

Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 29, 2026

@copilot these changes are test infra: src/libraries/sendtohelix-browser.targets, sendtohelix-wasi.targets

Restored the xunit3 changes (-notrait-trait-) to both files in 4dd3f11.

Comment thread eng/testing/xunit/xunit.targets Outdated
</PropertyGroup>

<!--
Override the xunit.v3.core.mtp-v1 validation target. The original target
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This feels like a situation where you could be using xunit.v3.extensibility.core instead of xunit.v3.core, especially if your custom runner replaces what xunit.v3.runner.inproc.console does. That would make sense in your situation (with a custom runner) and then these rules wouldn't end up being applied. In essence, xunit.v3.core is the package we think of as the package that says "you're planning to run your tests exactly how we intended for .NET Framework and/or .NET", and when you don't fit that mold, stepping away from that package makes sense to me.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

(I make this comment without understanding how your custom runner slots into anything. Feel free to ignore me. 😂)

xunit v3 relies on Assembly.Location which returns empty string in
NativeAOT, causing 'Argument was empty (Parameter AssemblyName)'.
xunit v4 (4.0.0-pre.33) fixes this internally.

Changes:
- Override XUnitV3Version to 4.0.0-pre.33 for TestNativeAot builds
- Update SingleFileTestRunner.cs for v4 API changes:
  - Namespace moves (ConsoleHelper, AssemblyMetadata, etc.)
  - Replace removed GetTargetFramework() with TargetFrameworkAttribute
  - Use non-obsolete Run() overload with resultWriters parameter

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

This comment has been minimized.

@agocke
Copy link
Copy Markdown
Member

agocke commented Mar 30, 2026

@copilot looks like there are api changes in the new xunit versions for the singlefiletestrunner: these failures are in the arm64 naot run: Running assembly:System.Collections.Tests, Version=11.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
Unhandled exception. System.ArgumentException: xunitVersion must be between 0 and 3 (Parameter 'xunitVersion')
at Xunit.Runner.Common.AssemblyMetadata..ctor(Int32 xunitVersion, String targetFramework) in //src/xunit.v3.runner.common/Utility/AssemblyMetadata.cs:line 42
at SingleFileTestRunner.Main(String[]) in /
/src/libraries/Common/tests/SingleFileTestRunner/SingleFileTestRunner.cs:line 60
at SingleFileTestRunner.Main(String[] args)
--- End of stack trace from previous location ---
at SingleFileTestRunner.

(String[] args)
DOTNET_DbgEnab

…ileTestRunner

The AssemblyMetadata constructor in xunit v3 only accepts xunitVersion
values 0-3. Reverts the v4 pre-release upgrade attempt (2c15bdf) and
restores the working xunit v3 code with AssemblyMetadata(3, ...).

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/b213ec25-ccc3-406a-a952-c9ea640003a5

Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
@github-actions

This comment has been minimized.

Instead of excluding System.Runtime.Tests from all TargetsMobile,
only exclude from Apple (crashes) and browser/wasi (xunit v2 error).
Android does not crash — it runs 0 tests gracefully.

Revert sendtohelixhelp.proj change (RunSmokeTestsOnly not available
in Helix send context).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 19, 2026 07:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@github-actions

This comment has been minimized.

The iOS-specific ItemGroups at lines 799 and 808 of tests.proj
unconditionally included System.Runtime.Tests for iOS builds with
ArchiveTests=true. This bypassed the SmokeTestProject flow which
properly excludes System.Runtime.Tests on Apple platforms (due to
XHarness xunit v2 incompatibility with xunit v3).

Add Condition="'$(RunSmokeTestsOnly)' != 'true'" to the
System.Runtime.Tests ProjectReference includes in both ItemGroups.
When RunSmokeTestsOnly=true, the SmokeTestProject items at line 584
(which have proper TargetOS exclusion conditions) control which tests
are included. The iOS functional tests (CoreCLR Interpreter/R2R) in
the same ItemGroups remain included since they don't use XHarness
test runners and pass successfully.

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

This comment has been minimized.

agocke and others added 2 commits April 19, 2026 18:01
The xunit v3 AOT source generator emits MemberData factory code that
references open type parameters (e.g. ICollection_Generic_Tests<T>) in
non-generic generated classes, causing CS0246 errors.

Fix by:
- Adding MemberType = typeof(TestBase) to MemberData attributes so the
  generator references the non-generic declaring type
- Moving EnumerableTestData, ListTestData, GetEnumerableTestData, and
  SetTestData from generic TestBase<T> to non-generic TestBase (they
  don't use T)
- Creating CollectionTestData class for project-specific data methods
  (IndexOfTestData, ValidCollectionSizes_GreaterThanOne, etc.) that
  were on generic classes but don't use the type parameter

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix CS0246 for System.IO.FileSystem.Tests NativeAOT build:
- Move GetSyncAsyncOptions from generic RandomAccess_Base<T> to FileSystemTest
- Add MemberType=typeof(FileSystemTest) for TrailingCharacters in InfoGetSetAttributes<T>
- Add MemberType=typeof(FileSystemTest) for GetSyncAsyncOptions in RandomAccess_Base<T>

Re-enable NativeAOT smoke tests that build+link successfully:
- System.Collections.Tests (CS0246 fixed in prior commit)
- System.IO.FileSystem.Tests (CS0246 fixed in this commit)
- System.Runtime.Tests (no AOT errors)
- System.Runtime.Intrinsics.Tests (no AOT errors)
- System.Threading.Tests (no AOT errors)
- System.Numerics.Vectors.Tests (no AOT errors)
- System.Runtime.InteropServices.Tests (no AOT errors)

Still disabled (3 of 11):
- System.IO.Compression.Tests (pre-existing CS0246 — new encoder/decoder types)
- System.Linq.Tests (ILC crash, exit code 134)
- System.Linq.Expressions.Tests (CS0619 obsolete DataAttribute.GetData)
- System.Reflection.Tests (CS0122/CS1525 non-public nested types)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 19, 2026 18:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

Work around xunit v3 AOT source generator issues:
- Linq.Expressions: add XUNIT_AOT conditional compilation for custom
  DataAttribute subclasses (PerCompilationTypeAttribute,
  InlinePerCompilationTypeAttribute) that call obsolete GetData (CS0619)
- Reflection: remove default parameter value causing CS4010/CS0103,
  convert multidimensional array typeof() InlineData to MemberData
  (CS0270/CS1525), make protected nested types public (CS0122)
- Re-enable both projects in NativeAOT smoke tests (10 of 11 enabled)

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

This comment has been minimized.

- Make RSNoCtor/RSCtor ref structs public (CS0122 in generated code)
- Make SignatureTypeTests.GenericType<T> public (CS0122 in generated code)
- Conditionally exclude [Trait] attribute in AOT mode (CS0117:
  FactTestCaseFactory does not contain a definition for 'Traits')

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 20, 2026 19:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

Copilot AI review requested due to automatic review settings April 21, 2026 03:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

agocke and others added 2 commits April 22, 2026 23:14
…ime-governance-docs

# Conflicts:
#	src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/Microsoft.Extensions.Options.Tests.csproj
#	src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj
#	src/libraries/System.Collections/tests/System.Collections.Tests.csproj
#	src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj
#	src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj
#	src/libraries/System.Diagnostics.DiagnosticSource/tests/System.Diagnostics.DiagnosticSource.Tests.csproj
#	src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj
#	src/libraries/System.Linq.Queryable/tests/System.Linq.Queryable.Tests.csproj
#	src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj
#	src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/System.Net.Http.WinHttpHandler.Unit.Tests.csproj
#	src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj
#	src/libraries/System.Net.WebProxy/tests/System.Net.WebProxy.Tests.csproj
#	src/libraries/System.Reflection.DispatchProxy/tests/System.Reflection.DispatchProxy.Tests.csproj
#	src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj
#	src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj
#	src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj
…ls is empty

On Windows, UninstallableSignals() returns Enumerable.Empty<object[]>().
In xunit v3, a Theory with no data rows fails with 'No data found'
instead of being silently skipped as in v2. Add SkipWhenEmpty = true.

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

This comment has been minimized.

The NativeAOT attribute stub for ConditionalTheoryAttribute is a plain
Attribute (not inheriting from TheoryAttribute), so it lacks properties
added in xunit v3. Add SkipWhenEmpty so test code using it compiles in
NativeAOT builds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 23, 2026 02:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

The property on TheoryAttribute in xunit v3 (4.0.0-pre.81) is
SkipTestWithoutData, not SkipWhenEmpty. Update both the test and
the NativeAOT attribute stub.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126277

Note

This review was generated by GitHub Copilot using multi-model analysis (Claude Opus 4.6 primary + GPT-5.3-Codex cross-review + two specialized Haiku sub-agents for infrastructure and test code).

Holistic Assessment

Motivation: Migrating library tests from xunit v2 to xunit v3 is a necessary infrastructure investment. xunit v3 drops the separate console runner in favor of self-hosted executables (MTP), adds Assert.Skip* APIs, and changes serialization/discovery rules. The massive scope (744 files, ~4300 insertions/deletions) is inherent to this kind of migration.

Approach: The approach is generally sound — moving package references from xunit v2 to v3, converting SkipTestException throws to Assert.SkipUnless/SkipWhen, adapting MemberData sources for v3's stricter empty-data rules, adding NativeAOT attribute stubs, and rewriting the SingleFileTestRunner for the v3 runner API. The FsCheck 2.x → 3.x migration (required since FsCheck.Xunit was removed) is also well-executed.

Summary: ⚠️ Needs Changes. The PR contains several issues that should be addressed before merge: 7 placeholder ActiveIssue annotations with fake issue number 0000, a production code change (CompositeMLDsa) mixed into a test migration PR, an undefined $(XUnitVersion) property that could break .NETFramework targets, and StaticTestGenerator left in a broken state. The core migration work (skip conditions, MemberData, infrastructure) is correct and well-done, but the loose ends need cleanup.


Detailed Findings

❌ Placeholder ActiveIssue annotations — 7 occurrences of issues/0000

Seven tests have been disabled with [ActiveIssue("https://github.com/dotnet/runtime/issues/0000")] — a placeholder that does not link to any real tracking issue. These must have real issue numbers filed before merge, or the problems they describe will be silently lost:

  • ErrObjectTests.ClearLastDllError non-zero in self-hosted runner
  • SqlXmlTest.CreateReader_TestAgainstBaseline — FileShare conflict (Windows)
  • ExceptionHandlingExpressions — DynamicMethod WrapNonExceptionThrows (Linux)
  • DispatchProxyTests — 2 occurrences (private proxy + internal service)
  • SatelliteAssemblies.SatelliteLoadsCorrectly_FromName — satellite assembly loading
  • DataContractSerializer.DCS_CollectionTypeInCollectibleALC — collectible ALC GC

Merge-blocking. Placeholder issues should never reach main.

❌ Production code change mixed into test migration PR — CompositeMLDsa.cs

Commit 4290344e6 adds ThrowIfNotSupported(algorithm) calls to ImportSubjectPublicKeyInfo and ImportPkcs8PrivateKey in src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsa.cs. While the change itself may be correct, it is a behavioral change to production cryptography code and should not be bundled in a test infrastructure migration PR. This should be split into its own PR with appropriate review.

Merge-blocking. Production code changes require separate review, especially in cryptography.

⚠️ $(XUnitVersion) undefined — stale xunit.runner.console reference

eng/testing/xunit/xunit.console.targets line 68 references $(XUnitVersion) for the xunit.runner.console package (used for .NETFramework targets). This property is no longer defined anywhere in the repo (the v2 package references that set it were removed). If any .NETFramework test project still uses this path, NuGet restore will fail with an empty version string. Either remove the dead reference or define the property.

⚠️ StaticTestGenerator left in inconsistent state

src/libraries/Common/tests/StaticTestGenerator/Program.cs was modified (removed using Xunit.Abstractions;, changed SkipTestExceptionSkipException, updated CLI args to -trait-) but its .csproj still references xunit v2 packages (xunit.core 2.4.1, xunit.abstractions 2.0.3). In xunit v2, ITestOutputHelper is in the Xunit.Abstractions namespace — removing that import while keeping v2 references will break compilation at typeof(ITestOutputHelper) (line 953). Additionally, the generated code template (line 1149) still references xunit.core.dll and xunit.assert.dll by their v2 assembly names. The tool is standalone (not built by CI), so this isn't immediately breaking, but it's now in a state where it can't be built or used. Either update the csproj to xunit v3 or revert the code changes.

⚠️ Tab characters in orderer files

The new xunit v3 overload methods in RandomTestCaseOrderer.cs (line 46) and RandomTestCollectionOrderer.cs (line 29) use tab characters for the where constraint line, while the rest of the files use spaces. This violates .editorconfig conventions.

⚠️ Stale mtp-v1 comments across multiple files

The MicrosoftTestingPlatformVersion is set to 2.2.1 (MTP v2), and the ILLink descriptor correctly references xunit.v3.mtp-v2. However, several comments in Directory.Build.targets, xunit.props, and xunit.targets still reference mtp-v1 (e.g., "xunit.v3.core.mtp-v1 NuGet package"). These should be updated to mtp-v2 for consistency and to avoid future confusion.

⚠️ NuGet.config adds nuget.org feed

The PR adds <add key="nuget" value="(api.nuget.org/redacted) /> to NuGet.config. The repo already has dotnet-public which mirrors nuget.org. Adding the direct feed may be needed for pre-release xunit v4 AOT packages, but this should be documented — and ideally removed once the packages are available on the internal feeds.


💡 Stale CopyRunnerToOutputDirectory logic

eng/testing/xunit/xunit.console.targets still contains the CopyRunnerToOutputDirectory target (lines 89–106) that copies xunit v2 console runner files. In xunit v3, the test DLL is self-hosted. This dead code is harmless but should be cleaned up in a follow-up.

💡 SingleFileTestRunner dropped CLI filters

The rewritten SingleFileTestRunner only handles -notrait/-trait- and -xml arguments. The previous version also supported -class, -method, -namespace, and -parallel. While these aren't passed by the current RunnerTemplate.sh/.cmd, they were available for manual debugging use. The xunit v3 runner likely handles some of these natively through its MTP entry point, but this trade-off should be documented.

💡 SingleFileTestRunnerpipelineStartup lifecycle

In SingleFileTestRunner.cs, pipelineStartup is created (line 88) before the try block (line 94). If CreateMessageHandler (line 91) throws, pipelineStartup.StopAsync() would not be called. Consider moving the pipeline startup into the try block.


✅ Skip Condition Inversions — All verified correct

All SkipTestExceptionAssert.SkipUnless/SkipWhen conversions were verified for De Morgan's law correctness. The known historical inversion (!IsWindows || !IsNotWindowsNanoServerSkipUnless(IsWindows && IsNotWindowsNanoServer) in HttpClientHandlerTest.Authentication.cs) is correctly fixed. (Verified across 3 independent models.)

✅ MemberData Migration — Correct patterns applied

MemberData sources that could return zero rows (e.g., algorithm support checks) were correctly converted to unconditional data sources with Assert.SkipUnless in the test body, or guarded with SkipWhenEmpty = true on ConditionalTheory.

✅ Generic Test Class Refactoring — Clean and complete

Collection test data moved from generic TestBase<T> to non-generic TestBase (as TestBase.NonGeneric), with all [MemberData] references updated with explicit MemberType. This is required because xunit v3's AOT source generator cannot resolve data from generic classes.

✅ FsCheck 2.x → 3.x Migration — Correct

CBOR property tests correctly migrated from [Property] attribute (FsCheck.Xunit, removed in FsCheck 3.x) to the Fluent API (FsCheck.Fluent, Check.One, FsCheck.FSharp.Prop.ForAll). All roundtrip tests preserved.

✅ Infrastructure — UseAppHost / OutputType / Package Split

The UseAppHost=false override chain (Directory.Build.targets → xunit.targets → tests.singlefile.targets) is correctly layered. Package references cleanly split between standard and NativeAOT AOT variants. ILLink descriptors updated for v3 assembly names. RunnerTemplate changes (DOTNET_ROOT export) are correct.

✅ AOT Attribute Stubs — Well-documented trade-off

AotXunitExtensions/AttributeStubs.cs clearly documents that ConditionalFact, ConditionalTheory, etc. become plain attributes in NativeAOT (not test-discoverable via their conditional logic). Only [Fact]/[Theory] tests run in NativeAOT mode. This is an acceptable pragmatic trade-off.

✅ Migration Documentation

docs/workflow/testing/libraries/xunit3-migration.md provides clear guidance for future contributors on the most common migration patterns. Good addition.

Generated by Code Review for issue #126277 ·

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

Labels

area-Meta linkable-framework Issues associated with delivering a linker friendly framework

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants