diff --git a/TUnit.Core/AbstractDynamicTest.cs b/TUnit.Core/AbstractDynamicTest.cs index e0d3464b6c..6097c24001 100644 --- a/TUnit.Core/AbstractDynamicTest.cs +++ b/TUnit.Core/AbstractDynamicTest.cs @@ -101,6 +101,11 @@ public class DynamicTest<[DynamicallyAccessedMembers( /// public int? CreatorLineNumber { get; set; } + /// + /// Custom display name for this dynamic test. If not set, a default name will be generated. + /// + public string? DisplayName { get; set; } + public override IEnumerable GetTests() { var result = new DynamicDiscoveryResult @@ -112,7 +117,8 @@ public override IEnumerable GetTests() TestClassType = typeof(T), CreatorFilePath = CreatorFilePath, CreatorLineNumber = CreatorLineNumber, - DynamicTestIndex = DynamicTestIndex + DynamicTestIndex = DynamicTestIndex, + DisplayName = DisplayName }; yield return result; diff --git a/TUnit.Core/DynamicTestMetadata.cs b/TUnit.Core/DynamicTestMetadata.cs new file mode 100644 index 0000000000..eb3d4e77f3 --- /dev/null +++ b/TUnit.Core/DynamicTestMetadata.cs @@ -0,0 +1,125 @@ +using System.Diagnostics.CodeAnalysis; + +namespace TUnit.Core; + +/// +/// Unified metadata class for dynamic tests. +/// Used by both AOT/source-generated mode and reflection mode for tests created via +/// DynamicTestBuilderAttribute or runtime test variant creation. +/// +public sealed class DynamicTestMetadata : TestMetadata, IDynamicTestMetadata +{ + private readonly DynamicDiscoveryResult _dynamicResult; + + public DynamicTestMetadata(DynamicDiscoveryResult dynamicResult) + { + _dynamicResult = dynamicResult; + } + + public int DynamicTestIndex => _dynamicResult.DynamicTestIndex; + + public string? DisplayName => _dynamicResult.DisplayName; + + /// + /// Parent test ID for test variants created at runtime. + /// + public string? ParentTestId => _dynamicResult.ParentTestId; + + /// + /// Relationship to parent test for test variants. + /// + public Enums.TestRelationship? Relationship => _dynamicResult.Relationship; + + /// + /// Custom properties for test variants. + /// + public Dictionary? Properties => _dynamicResult.Properties; + + [field: AllowNull, MaybeNull] + public override Func CreateExecutableTestFactory + { + get => field ??= CreateExecutableTest; + } + + private AbstractExecutableTest CreateExecutableTest(ExecutableTestCreationContext context, TestMetadata metadata) + { + var modifiedContext = new ExecutableTestCreationContext + { + TestId = context.TestId, + DisplayName = _dynamicResult.DisplayName ?? context.DisplayName, + Arguments = _dynamicResult.TestMethodArguments ?? context.Arguments, + ClassArguments = _dynamicResult.TestClassArguments ?? context.ClassArguments, + Context = context.Context, + TestClassInstanceFactory = context.TestClassInstanceFactory + }; + + // Apply runtime test variant properties + if (_dynamicResult.ParentTestId != null) + { + modifiedContext.Context.ParentTestId = _dynamicResult.ParentTestId; + } + + if (_dynamicResult.Relationship.HasValue) + { + modifiedContext.Context.Relationship = _dynamicResult.Relationship.Value; + } + + if (_dynamicResult.Properties != null) + { + foreach (var kvp in _dynamicResult.Properties) + { + modifiedContext.Context.StateBag.Items[kvp.Key] = kvp.Value; + } + } + + // Create instance factory + var createInstance = async (TestContext testContext) => + { + // If we have a factory from discovery, use it + if (modifiedContext.TestClassInstanceFactory != null) + { + return await modifiedContext.TestClassInstanceFactory(); + } + + // Check if there's a ClassConstructor to use + if (testContext.ClassConstructor != null) + { + var testBuilderContext = TestBuilderContext.FromTestContext(testContext, null); + var classConstructorMetadata = new ClassConstructorMetadata + { + TestSessionId = metadata.TestSessionId, + TestBuilderContext = testBuilderContext + }; + + return await testContext.ClassConstructor.Create(metadata.TestClassType, classConstructorMetadata); + } + + // Fall back to default instance factory + var instance = metadata.InstanceFactory(Type.EmptyTypes, modifiedContext.ClassArguments); + + // Handle property injections + foreach (var propertyInjection in metadata.PropertyInjections) + { + var value = propertyInjection.ValueFactory(); + propertyInjection.Setter(instance, value); + } + + return instance; + }; + + var invokeTest = metadata.TestInvoker ?? throw new InvalidOperationException("Test invoker is null"); + + return new ExecutableTest(createInstance, + async (instance, args, ctx, ct) => + { + await invokeTest(instance, args); + }) + { + TestId = modifiedContext.TestId, + Metadata = metadata, + Arguments = modifiedContext.Arguments, + ClassArguments = modifiedContext.ClassArguments, + Context = modifiedContext.Context + }; + } +} diff --git a/TUnit.Core/IDynamicTestMetadata.cs b/TUnit.Core/IDynamicTestMetadata.cs index 23b71dc093..4b4f2223ad 100644 --- a/TUnit.Core/IDynamicTestMetadata.cs +++ b/TUnit.Core/IDynamicTestMetadata.cs @@ -10,4 +10,9 @@ public interface IDynamicTestMetadata /// Used to generate unique test IDs when multiple dynamic tests target the same method. /// int DynamicTestIndex { get; } + + /// + /// Custom display name for this dynamic test. If null, a default name will be generated. + /// + string? DisplayName { get; } } \ No newline at end of file diff --git a/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs b/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs index 18a314bd48..b673db2071 100644 --- a/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs +++ b/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs @@ -131,7 +131,7 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco var testName = methodInfo.Name; - return Task.FromResult(new AotDynamicTestMetadata(result) + return Task.FromResult(new DynamicTestMetadata(result) { TestName = testName, TestClassType = result.TestClassType, @@ -296,74 +296,6 @@ private static MethodMetadata CreateDummyMethodMetadata(Type type, string method }; } - private sealed class AotDynamicTestMetadata(DynamicDiscoveryResult dynamicResult) : TestMetadata, IDynamicTestMetadata - { - public int DynamicTestIndex => dynamicResult.DynamicTestIndex; - - public override Func CreateExecutableTestFactory - { - get => (context, metadata) => - { - // For dynamic tests, we need to use the specific arguments from the dynamic result - var modifiedContext = new ExecutableTestCreationContext - { - TestId = context.TestId, - DisplayName = context.DisplayName, - Arguments = dynamicResult.TestMethodArguments ?? context.Arguments, - ClassArguments = dynamicResult.TestClassArguments ?? context.ClassArguments, - Context = context.Context - }; - - // Create instance and test invoker for the dynamic test - var createInstance = async (TestContext testContext) => - { - object instance; - - // Check if there's a ClassConstructor to use - if (testContext.ClassConstructor != null) - { - var testBuilderContext = TestBuilderContext.FromTestContext(testContext, null); - var classConstructorMetadata = new ClassConstructorMetadata - { - TestSessionId = "", // Dynamic tests don't have session IDs - TestBuilderContext = testBuilderContext - }; - - instance = await testContext.ClassConstructor.Create(metadata.TestClassType, classConstructorMetadata); - } - else - { - instance = metadata.InstanceFactory(Type.EmptyTypes, modifiedContext.ClassArguments); - } - - // Handle property injections - foreach (var propertyInjection in metadata.PropertyInjections) - { - var value = propertyInjection.ValueFactory(); - propertyInjection.Setter(instance, value); - } - - return instance; - }; - - var invokeTest = metadata.TestInvoker ?? throw new InvalidOperationException("Test invoker is null"); - - return new ExecutableTest(createInstance, - async (instance, args, context, ct) => - { - await invokeTest(instance, args); - }) - { - TestId = modifiedContext.TestId, - Metadata = metadata, - Arguments = modifiedContext.Arguments, - ClassArguments = modifiedContext.ClassArguments, - Context = modifiedContext.Context - }; - }; - } - } - private sealed class FailedDynamicTestMetadata(Exception exception) : TestMetadata { public override Func CreateExecutableTestFactory diff --git a/TUnit.Engine/Building/TestBuilderPipeline.cs b/TUnit.Engine/Building/TestBuilderPipeline.cs index 2e33d9baab..96da81767f 100644 --- a/TUnit.Engine/Building/TestBuilderPipeline.cs +++ b/TUnit.Engine/Building/TestBuilderPipeline.cs @@ -294,9 +294,11 @@ private async IAsyncEnumerable BuildTestsFromSingleMetad }; var testId = TestIdentifierService.GenerateTestId(resolvedMetadata, testData); + var dynamicMetadata = (IDynamicTestMetadata)resolvedMetadata; + var baseDisplayName = dynamicMetadata.DisplayName ?? resolvedMetadata.TestName; var displayName = repeatCount > 0 - ? $"{resolvedMetadata.TestName} (Repeat {repeatIndex + 1}/{repeatCount + 1})" - : resolvedMetadata.TestName; + ? $"{baseDisplayName} (Repeat {repeatIndex + 1}/{repeatCount + 1})" + : baseDisplayName; // Create TestDetails for dynamic tests var testDetails = new TestDetails @@ -326,6 +328,12 @@ private async IAsyncEnumerable BuildTestsFromSingleMetad // Set the TestDetails on the context context.Metadata.TestDetails = testDetails; + // Set custom display name for dynamic tests if specified + if (dynamicMetadata.DisplayName != null) + { + context.Metadata.DisplayName = dynamicMetadata.DisplayName; + } + // Invoke discovery event receivers to properly handle all attribute behaviors await InvokeDiscoveryEventReceiversAsync(context).ConfigureAwait(false); diff --git a/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs b/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs index e087d0229e..caac547fb9 100644 --- a/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs +++ b/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs @@ -1922,7 +1922,7 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco var testName = GenerateTestName(result.TestClassType, methodInfo); - var metadata = new DynamicReflectionTestMetadata(result.TestClassType, methodInfo, result) + var metadata = new DynamicTestMetadata(result) { TestName = testName, TestClassType = result.TestClassType, @@ -2091,85 +2091,4 @@ private static TestMetadata CreateFailedTestMetadataForDynamicTest(DynamicDiscov }; } - private sealed class DynamicReflectionTestMetadata : TestMetadata, IDynamicTestMetadata - { - private readonly DynamicDiscoveryResult _dynamicResult; - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] - private readonly Type _testClass; - private readonly MethodInfo _testMethod; - - public DynamicReflectionTestMetadata( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type testClass, - MethodInfo testMethod, - DynamicDiscoveryResult dynamicResult) - { - _testClass = testClass; - _testMethod = testMethod; - _dynamicResult = dynamicResult; - } - - public int DynamicTestIndex => _dynamicResult.DynamicTestIndex; - - public override Func CreateExecutableTestFactory - { - get => (context, metadata) => - { - // For dynamic tests, we need to use the specific arguments from the dynamic result - var modifiedContext = new ExecutableTestCreationContext - { - TestId = context.TestId, - DisplayName = context.DisplayName, - Arguments = _dynamicResult.TestMethodArguments ?? context.Arguments, - ClassArguments = _dynamicResult.TestClassArguments ?? context.ClassArguments, - Context = context.Context - }; - - // Create a regular ExecutableTest with the modified context - // Create instance and test invoker for the dynamic test - Func> createInstance = async (TestContext testContext) => - { - // Try to create instance with ClassConstructor attribute - var attributes = metadata.AttributeFactory(); - var classConstructorInstance = await ClassConstructorHelper.TryCreateInstanceWithClassConstructor( - attributes, - _testClass, - metadata.TestSessionId, - testContext).ConfigureAwait(false); - - if (classConstructorInstance != null) - { - return classConstructorInstance; - } - - // Fall back to default instance factory - var instance = metadata.InstanceFactory(Type.EmptyTypes, modifiedContext.ClassArguments); - - // Handle property injections - foreach (var propertyInjection in metadata.PropertyInjections) - { - var value = propertyInjection.ValueFactory(); - propertyInjection.Setter(instance, value); - } - - return instance; - }; - - var invokeTest = metadata.TestInvoker ?? throw new InvalidOperationException("Test invoker is null"); - - return new ExecutableTest(createInstance, - async (instance, args, context, ct) => - { - await invokeTest(instance, args).ConfigureAwait(false); - }) - { - TestId = modifiedContext.TestId, - Metadata = metadata, - Arguments = modifiedContext.Arguments, - ClassArguments = modifiedContext.ClassArguments, - Context = modifiedContext.Context - }; - }; - } - } - } diff --git a/TUnit.Engine/Services/TestRegistry.cs b/TUnit.Engine/Services/TestRegistry.cs index 3b4013f0fa..cc76b93a1d 100644 --- a/TUnit.Engine/Services/TestRegistry.cs +++ b/TUnit.Engine/Services/TestRegistry.cs @@ -256,7 +256,7 @@ private async Task CreateMetadataFromDynamicDiscoveryResult(Dynami var testName = methodInfo.Name; - return await Task.FromResult(new RuntimeDynamicTestMetadata(result.TestClassType, methodInfo, result) + return await Task.FromResult(new DynamicTestMetadata(result) { TestName = testName, TestClassType = result.TestClassType, @@ -340,83 +340,6 @@ private sealed class PendingDynamicTest } - private sealed class RuntimeDynamicTestMetadata : TestMetadata, IDynamicTestMetadata - { - private readonly DynamicDiscoveryResult _dynamicResult; - private readonly Type _testClass; - private readonly MethodInfo _testMethod; - - public RuntimeDynamicTestMetadata(Type testClass, MethodInfo testMethod, DynamicDiscoveryResult dynamicResult) - { - _testClass = testClass; - _testMethod = testMethod; - _dynamicResult = dynamicResult; - } - - public int DynamicTestIndex => _dynamicResult.DynamicTestIndex; - - public override Func CreateExecutableTestFactory - { - get => (context, metadata) => - { - var modifiedContext = new ExecutableTestCreationContext - { - TestId = context.TestId, - DisplayName = _dynamicResult.DisplayName ?? context.DisplayName, - Arguments = _dynamicResult.TestMethodArguments ?? context.Arguments, - ClassArguments = _dynamicResult.TestClassArguments ?? context.ClassArguments, - Context = context.Context - }; - - if (_dynamicResult.ParentTestId != null) - { - modifiedContext.Context.ParentTestId = _dynamicResult.ParentTestId; - } - - if (_dynamicResult.Relationship.HasValue) - { - modifiedContext.Context.Relationship = _dynamicResult.Relationship.Value; - } - - if (_dynamicResult.Properties != null) - { - foreach (var kvp in _dynamicResult.Properties) - { - modifiedContext.Context.StateBag.Items[kvp.Key] = kvp.Value; - } - } - - var createInstance = (TestContext testContext) => - { - var instance = metadata.InstanceFactory(Type.EmptyTypes, modifiedContext.ClassArguments); - - foreach (var propertyInjection in metadata.PropertyInjections) - { - var value = propertyInjection.ValueFactory(); - propertyInjection.Setter(instance, value); - } - - return Task.FromResult(instance); - }; - - var invokeTest = metadata.TestInvoker ?? throw new InvalidOperationException("Test invoker is null"); - - return new ExecutableTest(createInstance, - async (instance, args, context, ct) => - { - await invokeTest(instance, args); - }) - { - TestId = modifiedContext.TestId, - Metadata = metadata, - Arguments = modifiedContext.Arguments, - ClassArguments = modifiedContext.ClassArguments, - Context = modifiedContext.Context - }; - }; - } - } - /// /// Optimized method to get dependencies without LINQ allocations /// diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt index afda7f52fe..1e249359c3 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt @@ -646,6 +646,16 @@ namespace { public static T Argument() { } } + public sealed class DynamicTestMetadata : .TestMetadata, .IDynamicTestMetadata + { + public DynamicTestMetadata(.DynamicDiscoveryResult dynamicResult) { } + public override <.ExecutableTestCreationContext, .TestMetadata, .AbstractExecutableTest> CreateExecutableTestFactory { get; } + public string? DisplayName { get; } + public int DynamicTestIndex { get; } + public string? ParentTestId { get; } + public .? Properties { get; } + public .? Relationship { get; } + } public class DynamicTest<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicFields | ..NonPublicFields | ..PublicProperties)] T> : .AbstractDynamicTest, .IDynamicTestCreatorLocation where T : class { @@ -653,6 +663,7 @@ namespace public .<> Attributes { get; set; } public string? CreatorFilePath { get; set; } public int? CreatorLineNumber { get; set; } + public string? DisplayName { get; set; } public object?[]? TestClassArguments { get; set; } public .<>? TestMethod { get; set; } public object?[]? TestMethodArguments { get; set; } @@ -857,6 +868,7 @@ namespace } public interface IDynamicTestMetadata { + string? DisplayName { get; } int DynamicTestIndex { get; } } public interface IDynamicTestSource diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt index 5c77ae9d16..39b85adbb0 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt @@ -646,6 +646,16 @@ namespace { public static T Argument() { } } + public sealed class DynamicTestMetadata : .TestMetadata, .IDynamicTestMetadata + { + public DynamicTestMetadata(.DynamicDiscoveryResult dynamicResult) { } + public override <.ExecutableTestCreationContext, .TestMetadata, .AbstractExecutableTest> CreateExecutableTestFactory { get; } + public string? DisplayName { get; } + public int DynamicTestIndex { get; } + public string? ParentTestId { get; } + public .? Properties { get; } + public .? Relationship { get; } + } public class DynamicTest<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicFields | ..NonPublicFields | ..PublicProperties)] T> : .AbstractDynamicTest, .IDynamicTestCreatorLocation where T : class { @@ -653,6 +663,7 @@ namespace public .<> Attributes { get; set; } public string? CreatorFilePath { get; set; } public int? CreatorLineNumber { get; set; } + public string? DisplayName { get; set; } public object?[]? TestClassArguments { get; set; } public .<>? TestMethod { get; set; } public object?[]? TestMethodArguments { get; set; } @@ -857,6 +868,7 @@ namespace } public interface IDynamicTestMetadata { + string? DisplayName { get; } int DynamicTestIndex { get; } } public interface IDynamicTestSource diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt index 7d0b7502f7..c4adff816e 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt @@ -646,6 +646,16 @@ namespace { public static T Argument() { } } + public sealed class DynamicTestMetadata : .TestMetadata, .IDynamicTestMetadata + { + public DynamicTestMetadata(.DynamicDiscoveryResult dynamicResult) { } + public override <.ExecutableTestCreationContext, .TestMetadata, .AbstractExecutableTest> CreateExecutableTestFactory { get; } + public string? DisplayName { get; } + public int DynamicTestIndex { get; } + public string? ParentTestId { get; } + public .? Properties { get; } + public .? Relationship { get; } + } public class DynamicTest<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicFields | ..NonPublicFields | ..PublicProperties)] T> : .AbstractDynamicTest, .IDynamicTestCreatorLocation where T : class { @@ -653,6 +663,7 @@ namespace public .<> Attributes { get; set; } public string? CreatorFilePath { get; set; } public int? CreatorLineNumber { get; set; } + public string? DisplayName { get; set; } public object?[]? TestClassArguments { get; set; } public .<>? TestMethod { get; set; } public object?[]? TestMethodArguments { get; set; } @@ -857,6 +868,7 @@ namespace } public interface IDynamicTestMetadata { + string? DisplayName { get; } int DynamicTestIndex { get; } } public interface IDynamicTestSource diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt index 232141cff3..c5f7481604 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt @@ -623,6 +623,16 @@ namespace { public static T Argument() { } } + public sealed class DynamicTestMetadata : .TestMetadata, .IDynamicTestMetadata + { + public DynamicTestMetadata(.DynamicDiscoveryResult dynamicResult) { } + public override <.ExecutableTestCreationContext, .TestMetadata, .AbstractExecutableTest> CreateExecutableTestFactory { get; } + public string? DisplayName { get; } + public int DynamicTestIndex { get; } + public string? ParentTestId { get; } + public .? Properties { get; } + public .? Relationship { get; } + } public class DynamicTest : .AbstractDynamicTest, .IDynamicTestCreatorLocation where T : class { @@ -630,6 +640,7 @@ namespace public .<> Attributes { get; set; } public string? CreatorFilePath { get; set; } public int? CreatorLineNumber { get; set; } + public string? DisplayName { get; set; } public object?[]? TestClassArguments { get; set; } public .<>? TestMethod { get; set; } public object?[]? TestMethodArguments { get; set; } @@ -834,6 +845,7 @@ namespace } public interface IDynamicTestMetadata { + string? DisplayName { get; } int DynamicTestIndex { get; } } public interface IDynamicTestSource diff --git a/TUnit.TestProject/DynamicTests/DynamicTestDisplayNameTests.cs b/TUnit.TestProject/DynamicTests/DynamicTestDisplayNameTests.cs new file mode 100644 index 0000000000..627e4f1fe8 --- /dev/null +++ b/TUnit.TestProject/DynamicTests/DynamicTestDisplayNameTests.cs @@ -0,0 +1,62 @@ +using TUnit.TestProject.Attributes; + +namespace TUnit.TestProject.DynamicTests; + +/// +/// Tests that validate custom DisplayName is correctly applied to dynamic tests. +/// +[EngineTest(ExpectedResult.Pass)] +public class DynamicTestDisplayNameTests +{ + public async Task TestWithCustomDisplayName() + { + await Assert.That(TestContext.Current!.Metadata.DisplayName).IsEqualTo("My Custom Dynamic Test Name"); + } + + public async Task TestWithParameterizedDisplayName(int value) + { + await Assert.That(TestContext.Current!.Metadata.DisplayName).IsEqualTo($"Dynamic Test with value {value}"); + } + + public async Task TestWithDefaultDisplayName() + { + // When DisplayName is not set, it should fall back to the default generated name + await Assert.That(TestContext.Current!.Metadata.DisplayName).Contains("TestWithDefaultDisplayName"); + } + +#pragma warning disable TUnitWIP0001 + [DynamicTestBuilder] +#pragma warning restore TUnitWIP0001 + public void BuildTests(DynamicTestBuilderContext context) + { + // Test with a custom display name + context.AddTest(new DynamicTest + { + TestMethod = c => c.TestWithCustomDisplayName(), + DisplayName = "My Custom Dynamic Test Name" + }); + + // Test with parameterized display name + context.AddTest(new DynamicTest + { + TestMethod = c => c.TestWithParameterizedDisplayName(42), + TestMethodArguments = [42], + DisplayName = "Dynamic Test with value 42" + }); + + // Another parameterized test with different value + context.AddTest(new DynamicTest + { + TestMethod = c => c.TestWithParameterizedDisplayName(100), + TestMethodArguments = [100], + DisplayName = "Dynamic Test with value 100" + }); + + // Test without custom display name (should use default) + context.AddTest(new DynamicTest + { + TestMethod = c => c.TestWithDefaultDisplayName() + // DisplayName intentionally not set + }); + } +}