Skip to content

Commit 1b5705a

Browse files
chore(tests): migrate test suite from xUnit to NUnit 4.4.0, eliminate .shproj, and centralize TFMs (#321)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: glennawatson <[email protected]>
1 parent 9c173d4 commit 1b5705a

23 files changed

+251
-108
lines changed

.editorconfig

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,120 @@ csharp_style_prefer_top_level_statements = true:silent
525525
csharp_style_prefer_primary_constructors = true:suggestion
526526
csharp_style_prefer_local_over_anonymous_function = true:suggestion
527527

528+
529+
#############################################
530+
# NUnit Analyzers — enable all as errors
531+
#############################################
532+
533+
# Structure Rules (NUnit1001 - )
534+
dotnet_diagnostic.NUnit1001.severity = error # TestCase args must match parameter types
535+
dotnet_diagnostic.NUnit1002.severity = error # TestCaseSource should use nameof
536+
dotnet_diagnostic.NUnit1003.severity = error # TestCase provided too few arguments
537+
dotnet_diagnostic.NUnit1004.severity = error # TestCase provided too many arguments
538+
dotnet_diagnostic.NUnit1005.severity = error # ExpectedResult type must match return type
539+
dotnet_diagnostic.NUnit1006.severity = error # ExpectedResult must not be used on void methods
540+
dotnet_diagnostic.NUnit1007.severity = error # Non-void method but no ExpectedResult provided
541+
dotnet_diagnostic.NUnit1008.severity = error # ParallelScope.Self at assembly level has no effect
542+
dotnet_diagnostic.NUnit1009.severity = error # ParallelScope.Children on non-parameterized test
543+
dotnet_diagnostic.NUnit1010.severity = error # ParallelScope.Fixtures on a test method
544+
dotnet_diagnostic.NUnit1011.severity = error # TestCaseSource member does not exist
545+
dotnet_diagnostic.NUnit1012.severity = error # async test method must have non-void return type
546+
dotnet_diagnostic.NUnit1013.severity = error # async method must use non-generic Task when no result
547+
dotnet_diagnostic.NUnit1014.severity = error # async method must use Task<T> when result expected
548+
dotnet_diagnostic.NUnit1015.severity = error # Source type does not implement I(Async)Enumerable
549+
dotnet_diagnostic.NUnit1016.severity = error # Source type lacks default constructor
550+
dotnet_diagnostic.NUnit1017.severity = error # Specified source is not static
551+
dotnet_diagnostic.NUnit1018.severity = error # TestCaseSource param count mismatch (target method)
552+
dotnet_diagnostic.NUnit1019.severity = error # Source does not return I(Async)Enumerable
553+
dotnet_diagnostic.NUnit1020.severity = error # Parameters provided to field/property source
554+
dotnet_diagnostic.NUnit1021.severity = error # ValueSource should use nameof
555+
dotnet_diagnostic.NUnit1022.severity = error # Specified ValueSource is not static
556+
dotnet_diagnostic.NUnit1023.severity = error # ValueSource cannot supply required parameters
557+
dotnet_diagnostic.NUnit1024.severity = error # ValueSource does not return I(Async)Enumerable
558+
dotnet_diagnostic.NUnit1025.severity = error # ValueSource member does not exist
559+
dotnet_diagnostic.NUnit1026.severity = error # Test or setup/teardown method is not public
560+
dotnet_diagnostic.NUnit1027.severity = error # Test method has parameters but no arguments supplied
561+
dotnet_diagnostic.NUnit1028.severity = error # Non-test method is public
562+
dotnet_diagnostic.NUnit1029.severity = error # TestCaseSource param count mismatch (Test method)
563+
dotnet_diagnostic.NUnit1030.severity = error # TestCaseSource parameter type mismatch (Test method)
564+
dotnet_diagnostic.NUnit1031.severity = error # ValuesAttribute args must match parameter types
565+
dotnet_diagnostic.NUnit1032.severity = error # IDisposable field/property should be disposed in TearDown
566+
dotnet_diagnostic.NUnit1033.severity = error # TestContext.Write methods will be obsolete
567+
dotnet_diagnostic.NUnit1034.severity = error # Base TestFixtures should be abstract
568+
dotnet_diagnostic.NUnit1035.severity = error # Range 'step' parameter cannot be zero
569+
dotnet_diagnostic.NUnit1036.severity = error # Range: from < to when step is positive
570+
dotnet_diagnostic.NUnit1037.severity = error # Range: from > to when step is negative
571+
dotnet_diagnostic.NUnit1038.severity = error # Attribute values' types must match parameter type
572+
573+
# Assertion Rules (NUnit2001 - )
574+
dotnet_diagnostic.NUnit2001.severity = error # Prefer Assert.That(..., Is.False) over ClassicAssert.False
575+
dotnet_diagnostic.NUnit2002.severity = error # Prefer Assert.That(..., Is.False) over ClassicAssert.IsFalse
576+
dotnet_diagnostic.NUnit2003.severity = error # Prefer Assert.That(..., Is.True) over ClassicAssert.IsTrue
577+
dotnet_diagnostic.NUnit2004.severity = error # Prefer Assert.That(..., Is.True) over ClassicAssert.True
578+
dotnet_diagnostic.NUnit2005.severity = error # Prefer Is.EqualTo over AreEqual
579+
dotnet_diagnostic.NUnit2006.severity = error # Prefer Is.Not.EqualTo over AreNotEqual
580+
dotnet_diagnostic.NUnit2007.severity = error # Actual value should not be a constant
581+
dotnet_diagnostic.NUnit2008.severity = error # Incorrect IgnoreCase usage
582+
dotnet_diagnostic.NUnit2009.severity = error # Same value used for actual and expected
583+
dotnet_diagnostic.NUnit2010.severity = error # Use EqualConstraint for better messages
584+
dotnet_diagnostic.NUnit2011.severity = error # Use ContainsConstraint for better messages
585+
dotnet_diagnostic.NUnit2012.severity = error # Use StartsWithConstraint for better messages
586+
dotnet_diagnostic.NUnit2013.severity = error # Use EndsWithConstraint for better messages
587+
dotnet_diagnostic.NUnit2014.severity = error # Use SomeItemsConstraint for better messages
588+
dotnet_diagnostic.NUnit2015.severity = error # Prefer Is.SameAs over AreSame
589+
dotnet_diagnostic.NUnit2016.severity = error # Prefer Is.Null over ClassicAssert.Null
590+
dotnet_diagnostic.NUnit2017.severity = error # Prefer Is.Null over ClassicAssert.IsNull
591+
dotnet_diagnostic.NUnit2018.severity = error # Prefer Is.Not.Null over ClassicAssert.NotNull
592+
dotnet_diagnostic.NUnit2019.severity = error # Prefer Is.Not.Null over ClassicAssert.IsNotNull
593+
dotnet_diagnostic.NUnit2020.severity = error # Incompatible types for SameAs constraint
594+
dotnet_diagnostic.NUnit2021.severity = error # Incompatible types for EqualTo constraint
595+
dotnet_diagnostic.NUnit2022.severity = error # Missing property required for constraint
596+
dotnet_diagnostic.NUnit2023.severity = error # Invalid NullConstraint usage
597+
dotnet_diagnostic.NUnit2024.severity = error # Wrong actual type with String constraint
598+
dotnet_diagnostic.NUnit2025.severity = error # Wrong actual type with ContainsConstraint
599+
dotnet_diagnostic.NUnit2026.severity = error # Wrong actual type with SomeItems+EqualConstraint
600+
dotnet_diagnostic.NUnit2027.severity = error # Prefer Is.GreaterThan over ClassicAssert.Greater
601+
dotnet_diagnostic.NUnit2028.severity = error # Prefer Is.GreaterThanOrEqualTo over GreaterOrEqual
602+
dotnet_diagnostic.NUnit2029.severity = error # Prefer Is.LessThan over ClassicAssert.Less
603+
dotnet_diagnostic.NUnit2030.severity = error # Prefer Is.LessThanOrEqualTo over LessOrEqual
604+
dotnet_diagnostic.NUnit2031.severity = error # Prefer Is.Not.SameAs over AreNotSame
605+
dotnet_diagnostic.NUnit2032.severity = error # Prefer Is.Zero over ClassicAssert.Zero
606+
dotnet_diagnostic.NUnit2033.severity = error # Prefer Is.Not.Zero over ClassicAssert.NotZero
607+
dotnet_diagnostic.NUnit2034.severity = error # Prefer Is.NaN over ClassicAssert.IsNaN
608+
dotnet_diagnostic.NUnit2035.severity = error # Prefer Is.Empty over ClassicAssert.IsEmpty
609+
dotnet_diagnostic.NUnit2036.severity = error # Prefer Is.Not.Empty over ClassicAssert.IsNotEmpty
610+
dotnet_diagnostic.NUnit2037.severity = error # Prefer Does.Contain over ClassicAssert.Contains
611+
dotnet_diagnostic.NUnit2038.severity = error # Prefer Is.InstanceOf over ClassicAssert.IsInstanceOf
612+
dotnet_diagnostic.NUnit2039.severity = error # Prefer Is.Not.InstanceOf over ClassicAssert.IsNotInstanceOf
613+
dotnet_diagnostic.NUnit2040.severity = error # Non-reference types for SameAs constraint
614+
dotnet_diagnostic.NUnit2041.severity = error # Incompatible types for comparison constraint
615+
dotnet_diagnostic.NUnit2042.severity = error # Comparison constraint on object
616+
dotnet_diagnostic.NUnit2043.severity = error # Use ComparisonConstraint for better messages
617+
dotnet_diagnostic.NUnit2044.severity = error # Non-delegate actual parameter
618+
dotnet_diagnostic.NUnit2045.severity = error # Use Assert.EnterMultipleScope or Assert.Multiple
619+
dotnet_diagnostic.NUnit2046.severity = error # Use CollectionConstraint for better messages
620+
dotnet_diagnostic.NUnit2047.severity = error # Incompatible types for Within constraint
621+
dotnet_diagnostic.NUnit2048.severity = error # Prefer Assert.That over StringAssert
622+
dotnet_diagnostic.NUnit2049.severity = error # Prefer Assert.That over CollectionAssert
623+
dotnet_diagnostic.NUnit2050.severity = error # NUnit 4 no longer supports string.Format spec
624+
dotnet_diagnostic.NUnit2051.severity = error # Prefer Is.Positive over ClassicAssert.Positive
625+
dotnet_diagnostic.NUnit2052.severity = error # Prefer Is.Negative over ClassicAssert.Negative
626+
dotnet_diagnostic.NUnit2053.severity = error # Prefer Is.AssignableFrom over ClassicAssert.IsAssignableFrom
627+
dotnet_diagnostic.NUnit2054.severity = error # Prefer Is.Not.AssignableFrom over ClassicAssert.IsNotAssignableFrom
628+
dotnet_diagnostic.NUnit2055.severity = error # Prefer Is.InstanceOf<T> over 'is T' expression
629+
dotnet_diagnostic.NUnit2056.severity = error # Prefer Assert.EnterMultipleScope statement over Multiple
630+
631+
# Suppressor Rules (NUnit3001 - )
632+
dotnet_diagnostic.NUnit3001.severity = error # Expression checked in NotNull/IsNotNull/Assert.That
633+
dotnet_diagnostic.NUnit3002.severity = error # Field/Property initialized in SetUp/OneTimeSetUp
634+
dotnet_diagnostic.NUnit3003.severity = error # TestFixture instantiated via reflection
635+
dotnet_diagnostic.NUnit3004.severity = error # Field should be disposed in TearDown/OneTimeTearDown
636+
637+
# Style Rules (NUnit4001 - )
638+
dotnet_diagnostic.NUnit4001.severity = error # Simplify the Values attribute
639+
dotnet_diagnostic.NUnit4002.severity = error # Use Specific constraint
640+
641+
528642
# C++ Files
529643
[*.{cpp,h,in}]
530644
curly_bracket_next_line = true
@@ -551,5 +665,3 @@ indent_size = 2
551665
end_of_line = lf
552666
[*.{cmd, bat}]
553667
end_of_line = crlf
554-
555-
vsspell_dictionary_languages = en-US

src/Directory.Build.props

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@
3737
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
3838
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
3939
</PropertyGroup>
40+
41+
<!-- Centralized TFM Definitions -->
42+
<PropertyGroup>
43+
<!-- Roslyn projects target netstandard2.0 -->
44+
<RoslynTfm>netstandard2.0</RoslynTfm>
45+
<!-- Test projects multi-target net8.0, net9.0, and net10.0 -->
46+
<TestTfms>net8.0;net9.0;net10.0</TestTfms>
47+
</PropertyGroup>
48+
49+
<!-- MAUI TFMs with OS-specific conditional logic -->
50+
<PropertyGroup>
51+
<!-- Linux builds Android targets only -->
52+
<MauiTfms Condition="$([MSBuild]::IsOSPlatform('Linux'))">net9.0-android;net10.0-android</MauiTfms>
53+
<!-- macOS builds Android and Apple (iOS/MacCatalyst) targets -->
54+
<MauiTfms Condition="$([MSBuild]::IsOSPlatform('OSX'))">net9.0-android;net9.0-ios;net9.0-maccatalyst;net10.0-android;net10.0-ios;net10.0-maccatalyst</MauiTfms>
55+
<!-- Windows builds Android, Windows, and Apple targets (assuming paired Mac) -->
56+
<MauiTfms Condition="$([MSBuild]::IsOSPlatform('Windows'))">net9.0-android;net9.0-ios;net9.0-maccatalyst;net9.0-windows10.0.19041.0;net10.0-android;net10.0-ios;net10.0-maccatalyst;net10.0-windows10.0.19041.0</MauiTfms>
57+
</PropertyGroup>
58+
4059
<ItemGroup Condition="'$(IsTestProject)' != 'true'">
4160
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
4261
</ItemGroup>

src/Directory.Packages.props

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,14 @@
3131
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0" />
3232
<PackageVersion Include="ReactiveUI.Maui" Version="22.2.1" />
3333
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
34-
<PackageVersion Include="System.Formats.Asn1" Version="9.0.0" />
35-
<PackageVersion Include="xunit" Version="2.9.3" />
36-
<PackageVersion Include="xunit.runner.console" Version="2.9.3" />
37-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
38-
<PackageVersion Include="Xunit.StaFact" Version="3.0.13" />
39-
<PackageVersion Include="FluentAssertions" Version="8.7.1" />
34+
<PackageVersion Include="System.Formats.Asn1" Version="9.0.10" />
35+
<PackageVersion Include="NUnit" Version="4.4.0" />
36+
<PackageVersion Include="NUnit3TestAdapter" Version="5.2.0" />
37+
<PackageVersion Include="NUnit.Analyzers" Version="4.10.0" />
4038
<PackageVersion Include="Microsoft.Reactive.Testing" Version="6.1.0" />
4139
<PackageVersion Include="PublicApiGenerator" Version="11.5.0" />
4240
<PackageVersion Include="coverlet.msbuild" Version="6.0.4" />
43-
<PackageVersion Include="Verify.Xunit" Version="31.0.2" />
41+
<PackageVersion Include="Verify.NUnit" Version="31.0.4" />
4442
<PackageVersion Include="Verify.SourceGenerators" Version="2.5.0" />
4543
<PackageVersion Include="ReactiveMarbles.SourceGenerator.TestNuGetHelper" Version="1.3.1" />
4644
<PackageVersion Include="Basic.Reference.Assemblies.Net80" Version="1.8.3" />
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) 2025 ReactiveUI and contributors. All rights reserved.
2+
// Licensed to the ReactiveUI and contributors under one or more agreements.
3+
// The ReactiveUI and contributors licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using NUnit.Framework;
7+
8+
[assembly: Parallelizable(ParallelScope.Fixtures)]
9+
[assembly: LevelOfParallelism(4)]

src/ReactiveUI.SourceGenerator.Tests/ReactiveUI.SourceGenerators.Tests.csproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFrameworks>$(TestTfms)</TargetFrameworks>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<LangVersion>13.0</LangVersion>
@@ -16,22 +16,22 @@
1616
<PackageReference Include="NuGet.Common" />
1717
<PackageReference Include="NuGet.Protocol" />
1818
<PackageReference Include="System.Formats.Asn1" />
19-
<PackageReference Include="xunit" />
20-
<PackageReference Include="xunit.runner.visualstudio" />
19+
<PackageReference Include="NUnit" />
20+
<PackageReference Include="NUnit3TestAdapter" />
21+
<PackageReference Include="NUnit.Analyzers" />
2122
<PackageReference Include="ReactiveMarbles.SourceGenerator.TestNuGetHelper" />
22-
<PackageReference Include="Verify.Xunit" />
23+
<PackageReference Include="Verify.NUnit" />
2324
<PackageReference Include="Verify.SourceGenerators" />
2425
<PackageReference Include="Basic.Reference.Assemblies.Net80" />
2526
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" VersionOverride="4.12.0" />
2627
<PackageReference Include="Microsoft.CodeAnalysis.Common" PrivateAssets="all" VersionOverride="4.12.0" />
2728
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" PrivateAssets="all" VersionOverride="4.12.0" />
2829
<PackageReference Include="Microsoft.CodeAnalysis" PrivateAssets="all" VersionOverride="4.12.0" />
2930
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" PrivateAssets="all" VersionOverride="4.12.0" />
30-
<PackageReference Include="FluentAssertions" />
3131
</ItemGroup>
3232

3333
<ItemGroup>
34-
<Using Include="Xunit" />
34+
<Using Include="NUnit.Framework" />
3535
</ItemGroup>
3636

3737
<ItemGroup>

src/ReactiveUI.SourceGenerator.Tests/TestBase.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,36 @@
44
// See the LICENSE file in the project root for full license information.
55

66
using Microsoft.CodeAnalysis;
7-
using Xunit.Abstractions;
87

98
namespace ReactiveUI.SourceGenerator.Tests;
109

1110
/// <summary>
1211
/// A base class for handling test setup and teardown.
1312
/// </summary>
1413
/// <typeparam name="T">Type of Incremental Generator.</typeparam>
15-
/// <seealso cref="Xunit.IAsyncLifetime" />
1614
/// <seealso cref="System.IDisposable" />
17-
/// <param name="testOutputHelper">The output helper.</param>
18-
public abstract class TestBase<T>(ITestOutputHelper testOutputHelper) : IAsyncLifetime, IDisposable
15+
public abstract class TestBase<T> : IDisposable
1916
where T : IIncrementalGenerator, new()
2017
{
2118
/// <summary>
2219
/// Gets the TestHelper instance.
2320
/// </summary>
24-
protected TestHelper<T> TestHelper { get; } = new(testOutputHelper);
21+
protected TestHelper<T> TestHelper { get; } = new();
2522

26-
/// <inheritdoc/>
23+
/// <summary>
24+
/// Initializes the test helper asynchronously.
25+
/// </summary>
26+
/// <returns>A task representing the asynchronous operation.</returns>
27+
[OneTimeSetUp]
2728
public Task InitializeAsync() => TestHelper.InitializeAsync();
2829

29-
/// <inheritdoc/>
30-
public Task DisposeAsync()
30+
/// <summary>
31+
/// Disposes the test helper.
32+
/// </summary>
33+
[OneTimeTearDown]
34+
public void DisposeAsync()
3135
{
3236
TestHelper.Dispose();
33-
return Task.CompletedTask;
3437
}
3538

3639
/// <inheritdoc/>

src/ReactiveUI.SourceGenerator.Tests/TestHelper.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,22 @@
33
// The ReactiveUI and contributors licenses this file to you under the MIT license.
44
// See the LICENSE file in the project root for full license information.
55

6-
using FluentAssertions;
7-
86
using Microsoft.CodeAnalysis;
97
using Microsoft.CodeAnalysis.CSharp;
108

119
using NuGet.Frameworks;
1210
using NuGet.LibraryModel;
1311
using NuGet.Versioning;
1412

13+
using NUnit.Framework;
14+
1515
using ReactiveMarbles.NuGet.Helpers;
1616

1717
using ReactiveMarbles.SourceGenerator.TestNuGetHelper.Compilation;
1818

1919
using ReactiveUI.SourceGenerators;
2020
using ReactiveUI.SourceGenerators.WinForms;
2121

22-
using Xunit.Abstractions;
23-
2422
namespace ReactiveUI.SourceGenerator.Tests;
2523

2624
/// <summary>
@@ -29,8 +27,7 @@ namespace ReactiveUI.SourceGenerator.Tests;
2927
/// </summary>
3028
/// <typeparam name="T">Type of Incremental Generator.</typeparam>
3129
/// <seealso cref="System.IDisposable" />
32-
/// <param name="testOutput">The test output helper for capturing test logs.</param>
33-
public sealed class TestHelper<T>(ITestOutputHelper testOutput) : IDisposable
30+
public sealed class TestHelper<T> : IDisposable
3431
where T : IIncrementalGenerator, new()
3532
{
3633
#pragma warning disable CS0618 // Type or member is obsolete
@@ -127,7 +124,7 @@ public void TestFail(
127124
throw new InvalidOperationException("Must have valid compiler instance.");
128125
}
129126

130-
var utility = new SourceGeneratorUtility(x => testOutput.WriteLine(x));
127+
var utility = new SourceGeneratorUtility(x => TestContext.Out.WriteLine(x));
131128

132129
#pragma warning disable IDE0053 // Use expression body for lambda expression
133130
#pragma warning disable RCS1021 // Convert lambda expression body to expression body
@@ -204,7 +201,7 @@ public SettingsTask RunGeneratorAndCheck(
204201
var prediagnostics = compilation.GetDiagnostics()
205202
.Where(d => d.Severity > DiagnosticSeverity.Warning)
206203
.ToList();
207-
prediagnostics.Should().BeEmpty();
204+
Assert.That(prediagnostics, Is.Empty);
208205
}
209206

210207
var generator = new T();
@@ -224,7 +221,7 @@ public SettingsTask RunGeneratorAndCheck(
224221
{
225222
foreach (var diagnostic in offendingDiagnostics)
226223
{
227-
testOutput.WriteLine($"Diagnostic: {diagnostic.Id} - {diagnostic.GetMessage()}");
224+
TestContext.Out.WriteLine($"Diagnostic: {diagnostic.Id} - {diagnostic.GetMessage()}");
228225
}
229226

230227
throw new InvalidOperationException("Compilation failed due to the above diagnostics.");

src/ReactiveUI.SourceGenerator.Tests/UnitTests/BindableDerivedListGeneratorTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@
44
// See the LICENSE file in the project root for full license information.
55

66
using ReactiveUI.SourceGenerators;
7-
using Xunit.Abstractions;
87

98
namespace ReactiveUI.SourceGenerator.Tests;
109

1110
/// <summary>
1211
/// BindableDerivedListGeneratorTests.
1312
/// </summary>
14-
public class BindableDerivedListGeneratorTests(ITestOutputHelper output) : TestBase<BindableDerivedListGenerator>(output)
13+
[TestFixture]
14+
public class BindableDerivedListGeneratorTests : TestBase<BindableDerivedListGenerator>
1515
{
1616
/// <summary>
1717
/// Tests that the source generator correctly generates reactive properties.
1818
/// </summary>
1919
/// <returns>A task to monitor the async.</returns>
20-
[Fact]
20+
[Test]
2121
public Task FromReactiveProperties()
2222
{
2323
// Arrange: Setup the source code that matches the generator input expectations.

0 commit comments

Comments
 (0)