Tags: thomhurst/TUnit
Tags
fix: pass empty array to params parameter when [Arguments] has no val… …ues (#4572) When [Arguments] is used with no arguments and the test method has a params parameter, the parameter now correctly receives an empty array instead of null. This matches standard C# behavior where calling a method with params and no arguments passes an empty array. Fixes #4561 Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
feat: add SharedDataSources helper for custom data source attributes (#… …4564) * feat: add SharedDataSources helper for custom data source attributes Add a public SharedDataSources class that allows users to implement custom data source attributes with the same sharing behavior (SharedType and Key) as ClassDataSourceAttribute. This addresses the request in discussion #4536 for a way to extend or reuse the functionality from ClassDataSources without exposing internal implementation details. The API provides multiple overloads: - Generic with new() constraint for simple default construction - Generic with factory for custom initialization - Non-generic for runtime type scenarios Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: resolve build errors for netstandard2.0 compatibility - Replace ArgumentNullException.ThrowIfNull with null-coalescing throw pattern - Add null-forgiving operators to TestDataContainer return values - Add null-forgiving operators to key parameter after null check Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: update public API snapshots for SharedDataSources Add SharedDataSources class to the public API verified files for DotNet8_0, DotNet9_0, and DotNet10_0. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: update Net4_7 public API snapshot for SharedDataSources Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add DynamicallyAccessedMembers AOT annotations to Type parameters Address PR review feedback: - Add [DynamicallyAccessedMembers] attribute to Type parameters in non-generic GetOrCreate overloads for Native AOT compatibility - Update public API snapshots with the new signatures Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove AOT annotations from Net4_7 snapshot The PublicApiGenerator doesn't render DynamicallyAccessedMembers attributes in netstandard2.0/net472 target frameworks. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: make testClassType and key optional in non-factory overloads This enables cleaner API calls: - SharedDataSources.GetOrCreate<T>(SharedType.PerTestSession) - SharedDataSources.GetOrCreate<T>(SharedType.Keyed, key: "mykey") Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
fix: resolve multiple migration code fixer bugs (#4557) * fix: resolve multiple migration code fixer bugs This commit addresses several issues in the NUnit and xUnit migration code fixers: - Fix using directive removal in namespace blocks (#4486, #4482) Extended RemoveFrameworkUsings() to also remove using directives from NamespaceDeclarationSyntax and FileScopedNamespaceDeclarationSyntax - Fix preprocessor directive corruption (#4481, #4487, #4488, #4492) Updated CleanupClassMemberLeadingTrivia() to preserve #region, #if, #endif, #pragma, and other preprocessor directives. Only removes excessive consecutive blank lines, not all newlines. - Fix Platform attribute conversion (#4489) Removed conversion that generated non-existent [ExcludeOn] attribute. Platform attribute is now removed during migration. - Fix FixtureLifeCycle attribute handling (#4490) Added FixtureLifeCycle to recognized and removable attributes. TUnit uses instance-per-test by default. - Fix Assert.Throws tracking (#4483) Updated ConvertThrows/ConvertThrowsAsync to return original expression instead of null, ensuring assertions are tracked in conversion plan. - Fix async return type wrapping (#4491) Added WrapReturnTypeInTask support for non-void, non-Task return types. Methods returning object/int now correctly become Task<object>/Task<int>. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: restore Platform attribute conversion to RunOn/ExcludeOn TUnit does have ExcludeOnAttribute, so the Platform attribute conversion should be kept. Only removed Platform from NUnitRemovableAttributeNames. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
fix: flush console output after test completion to prevent truncation (… …#4545) (#4553) ## Problem Console output was being truncated when tests completed, particularly when tests ended with Console.Write() without a newline. Users reported that "the end of the output is cut" even after the previous fix in c01a6fc. ## Root Cause While commit c01a6fc fixed parallel output mixing by using per-context buffers, it didn't address output truncation at test completion. When a test ends, any buffered console output (from Console.Write without newline) remains in the test context's line buffer but is never flushed to the sinks. This buffered output is lost and doesn't appear in test results or IDE output. ## Solution Added explicit flushing of console interceptors (stdout and stderr) in the TestCoordinator.ExecuteTestInternalAsync() finally block. This ensures all buffered output is captured before test results are reported. The flush happens: - After test execution completes - In the finally block (always executes, even on exception) - Before result reporting (so output is available in results) - While TestContext.Current still points to the test context - With error handling to prevent flush failures from breaking tests ## Testing - Added OutputTruncationTests with tests ending in Console.Write() - Enhanced ParallelConsoleOutputTests with truncation test case - Existing parallel output isolation tests continue to pass Fixes #4545 Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
fix: actually load assemblies in InfrastructureGenerator (#4541) (#4550) ## Problem Hooks in referenced library assemblies were not executing because the InfrastructureGenerator queued assembly loaders but never invoked them. ## Root Cause The InfrastructureGenerator called `SourceRegistrar.RegisterAssembly()` which added loaders to `Sources.AssemblyLoaders` queue, but this queue was never processed. Assemblies were never loaded, so their ModuleInitializers (which register hooks) never executed. ## Solution Changed the generated code to directly load assemblies via `Assembly.Load()` in the ModuleInitializer, instead of queuing loaders that are never invoked. This ensures: 1. Referenced assemblies are loaded early during module initialization 2. Their ModuleInitializers execute and register hooks globally 3. Hooks from library assemblies work correctly ## Testing - Added AbstractTestSessionHookTests to verify hooks in abstract base classes work - Verified hooks from TUnit.TestProject.Library execute correctly Fixes #4541 Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
fix: CI infrastructure issues (#4502) * fix: CI infrastructure issues - Fix flaky WaitsFor_Performance_Many_Quick_Polls test on net472 - The 1ms polling interval was unrealistic on .NET Framework where the minimum timer resolution is ~15ms - Changed to 10ms interval and reduced target count from 100 to 20 - Add net10.0 target framework to FSharp and VB NuGet tester projects - Pipeline was running with --framework net10.0 but projects only supported up to net9.0 * fix: remove platform restrictions from FSharp/VB nuget test modules
refactor: implement two-phase architecture for xUnit migration code f… …ixer (#4477) * refactor: implement two-phase architecture for xUnit migration code fixer This change introduces a robust two-phase migration architecture that separates semantic analysis from syntax transformation, eliminating semantic model staleness issues that plagued the previous rewriter-based approach. Key changes: **New Two-Phase Architecture:** - Phase 1 (Analysis): Collects all conversion targets while semantic model is valid - Phase 2 (Transformation): Applies pure syntax transformations using annotations - Uses SyntaxAnnotation to track nodes across tree modifications **New Files:** - `Base/TwoPhase/MigrationAnalyzer.cs` - Base class for framework analyzers - `Base/TwoPhase/MigrationTransformer.cs` - Syntax transformation engine - `Base/TwoPhase/ConversionPlan.cs` - Data structures for conversion targets - `TwoPhase/XUnitTwoPhaseAnalyzer.cs` - xUnit-specific analyzer implementation - `Base/MigrationContext.cs` - Error tracking for legacy fallback path **xUnit Migration Improvements:** - Assert.Throws/ThrowsAsync now kept unchanged (TUnit has compatible API) - .Because() message handling for True/False assertions - Proper [Before(Test)]/[After(Test)] attribute generation - TheoryData<T> → IEnumerable<T> conversion - Record.Exception → try-catch block generation - ITestOutputHelper → Console.WriteLine conversion **Code Cleanup:** - Removed 1,762 lines of legacy rewriter code from XUnitMigrationCodeFixProvider - File reduced from 1,849 lines to 87 lines (95% reduction) - Legacy code replaced with simple pass-through implementations All 551 analyzer tests pass. * feat(assertions): add StrictEqual, PropertyChanged, and Raises assertions Implement previously missing xUnit assertion equivalents: - IsStrictlyEqualTo/IsNotStrictlyEqualTo: Uses object.Equals() instead of IEquatable<T> for strict equality comparison - PropertyChanged/PropertyChangedAsync: Monitor INotifyPropertyChanged events - Raises/RaisesAsync/RaisesAny/RaisesAnyAsync: Monitor event raising with type-specific or base EventArgs Update XUnitTwoPhaseAnalyzer to convert Assert.StrictEqual to the new TUnit fluent assertion. PropertyChanged and Raises assertions use the same API as xUnit, so they migrate via namespace change only. Add comprehensive tests for all new assertions. * feat: implement two-phase architecture for NUnit and MSTest migration - Add NUnitTwoPhaseAnalyzer and MSTestTwoPhaseAnalyzer for semantic analysis phase before syntax transformation - Add NUnitAssertMultipleRewriter to convert Assert.Multiple(() => {}) to using (Assert.Multiple()) {} - Fix ExpectedResult handling: properly rename TestCase to Arguments and add System.Threading.Tasks using after post-transformations - Fix ExpectedException handling: make methods async when wrapping body in await Assert.ThrowsAsync<T>() - Fix ref/out parameter handling: use .Wait() instead of await since C# doesn't allow ref/out parameters in async methods - Update test expectations to match correct property ordering and constraint handling All 130 NUnit migration tests now pass. * test: add edge case tests for ref/out parameter handling - Add test for multiple assertions in ref parameter method - Add test for Assert.Multiple inside ref parameter method Both tests verify that .Wait() is used instead of await when the containing method has ref/out parameters. * test: add comprehensive migration tests for xUnit and MSTest Add new test coverage inspired by NUnit's extensive test suite: xUnit tests added (7): - ref/out parameter handling (use .Wait() instead of async) - Interface implementation preservation - Nested class migration - Multiple classes in file - Record.Exception DoesNotThrow pattern - Generic test class migration MSTest tests added (3): - ref/out parameter handling - Interface implementation preservation Also fixes MSTest format string and comparer detection in assertions.
docs: add framework flag tip for multi-targeting projects in migratio… …n guides When running dotnet format on projects that target multiple .NET versions, users should specify --framework with their latest supported TFM to avoid issues. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PreviousNext