diff --git a/TUnit.Assertions/Conditions/HasDistinctItemsAssertion.cs b/TUnit.Assertions/Conditions/HasDistinctItemsAssertion.cs index f54ac31630..b7a8eb0e45 100644 --- a/TUnit.Assertions/Conditions/HasDistinctItemsAssertion.cs +++ b/TUnit.Assertions/Conditions/HasDistinctItemsAssertion.cs @@ -11,12 +11,22 @@ namespace TUnit.Assertions.Conditions; public class HasDistinctItemsAssertion : Sources.CollectionAssertionBase where TCollection : IEnumerable { + private readonly IEqualityComparer? _comparer; + public HasDistinctItemsAssertion( AssertionContext context) : base(context) { } + public HasDistinctItemsAssertion( + AssertionContext context, + IEqualityComparer comparer) + : base(context) + { + _comparer = comparer; + } + protected override Task CheckAsync(EvaluationMetadata metadata) { if (metadata.Exception != null) @@ -30,7 +40,7 @@ protected override Task CheckAsync(EvaluationMetadata(metadata.Value); - return Task.FromResult(CollectionChecks.CheckHasDistinctItems(adapter)); + return Task.FromResult(CollectionChecks.CheckHasDistinctItems(adapter, _comparer)); } protected override string GetExpectation() => "to have distinct items"; diff --git a/TUnit.Assertions/Conditions/StringEqualsAssertion.cs b/TUnit.Assertions/Conditions/StringEqualsAssertion.cs index 32e386c21e..82134374ae 100644 --- a/TUnit.Assertions/Conditions/StringEqualsAssertion.cs +++ b/TUnit.Assertions/Conditions/StringEqualsAssertion.cs @@ -13,6 +13,7 @@ namespace TUnit.Assertions.Conditions; public class StringEqualsAssertion : Assertion { private readonly string? _expected; + private readonly IEqualityComparer? _comparer; private StringComparison _comparison = StringComparison.Ordinal; private bool _trimming; private bool _nullAndEmptyEquality; @@ -36,6 +37,16 @@ public StringEqualsAssertion( _comparison = comparison; } + public StringEqualsAssertion( + AssertionContext context, + string? expected, + IEqualityComparer comparer) + : base(context) + { + _expected = expected; + _comparer = comparer; + } + /// /// Makes the comparison case-insensitive. /// @@ -112,6 +123,17 @@ protected override Task CheckAsync(EvaluationMetadata expectedValue = string.IsNullOrEmpty(expectedValue) ? null : expectedValue; } + // When a custom comparer is provided, use it directly + if (_comparer != null) + { + if (_comparer.Equals(actualValue!, expectedValue!)) + { + return AssertionResult._passedTask; + } + + return Task.FromResult(AssertionResult.Failed($"found \"{value}\"")); + } + if (string.Equals(actualValue, expectedValue, _comparison)) { return AssertionResult._passedTask; diff --git a/TUnit.Assertions/Sources/CollectionAssertionBase.cs b/TUnit.Assertions/Sources/CollectionAssertionBase.cs index 0a842a097e..a72b6b18cb 100644 --- a/TUnit.Assertions/Sources/CollectionAssertionBase.cs +++ b/TUnit.Assertions/Sources/CollectionAssertionBase.cs @@ -91,6 +91,21 @@ public CollectionContainsAssertion Contains( return new CollectionContainsAssertion(Context, expected); } + /// + /// Asserts that the collection contains the expected item using a custom equality comparer. + /// This instance method enables calling Contains with proper type inference and a custom comparer. + /// Example: await Assert.That(list).Contains("value", StringComparer.OrdinalIgnoreCase); + /// + public CollectionContainsAssertion Contains( + TItem expected, + IEqualityComparer comparer, + [CallerArgumentExpression(nameof(expected))] string? expectedExpression = null, + [CallerArgumentExpression(nameof(comparer))] string? comparerExpression = null) + { + Context.ExpressionBuilder.Append($".Contains({expectedExpression}, {comparerExpression})"); + return new CollectionContainsAssertion(Context, expected, comparer); + } + /// /// Asserts that the collection contains an item matching the predicate. /// This instance method enables calling Contains with proper type inference. @@ -284,6 +299,19 @@ public HasDistinctItemsAssertion HasDistinctItems() return new HasDistinctItemsAssertion(Context); } + /// + /// Asserts that the collection contains only distinct (unique) items using a custom equality comparer. + /// This instance method enables calling HasDistinctItems with proper type inference and a custom comparer. + /// Example: await Assert.That(list).HasDistinctItems(StringComparer.OrdinalIgnoreCase); + /// + public HasDistinctItemsAssertion HasDistinctItems( + IEqualityComparer comparer, + [CallerArgumentExpression(nameof(comparer))] string? comparerExpression = null) + { + Context.ExpressionBuilder.Append($".HasDistinctItems({comparerExpression})"); + return new HasDistinctItemsAssertion(Context, comparer); + } + /// /// Asserts that the collection does not contain the specified item. /// This instance method enables calling DoesNotContain with proper type inference. @@ -297,6 +325,21 @@ public CollectionDoesNotContainAssertion DoesNotContain( return new CollectionDoesNotContainAssertion(Context, expected); } + /// + /// Asserts that the collection does not contain the specified item using a custom equality comparer. + /// This instance method enables calling DoesNotContain with proper type inference and a custom comparer. + /// Example: await Assert.That(list).DoesNotContain("value", StringComparer.OrdinalIgnoreCase); + /// + public CollectionDoesNotContainAssertion DoesNotContain( + TItem expected, + IEqualityComparer comparer, + [CallerArgumentExpression(nameof(expected))] string? expectedExpression = null, + [CallerArgumentExpression(nameof(comparer))] string? comparerExpression = null) + { + Context.ExpressionBuilder.Append($".DoesNotContain({expectedExpression}, {comparerExpression})"); + return new CollectionDoesNotContainAssertion(Context, expected, comparer); + } + /// /// Asserts that the collection does not contain any item matching the predicate. /// This instance method enables calling DoesNotContain with proper type inference. diff --git a/TUnit.Assertions/Sources/MemoryAssertionBase.cs b/TUnit.Assertions/Sources/MemoryAssertionBase.cs index 20ba2d74fc..d80f5ba8d9 100644 --- a/TUnit.Assertions/Sources/MemoryAssertionBase.cs +++ b/TUnit.Assertions/Sources/MemoryAssertionBase.cs @@ -104,6 +104,19 @@ public MemoryContainsAssertion Contains( return new MemoryContainsAssertion(Context, CreateAdapter, expected); } + /// + /// Asserts that the memory contains the expected item using a custom equality comparer. + /// + public MemoryContainsAssertion Contains( + TItem expected, + IEqualityComparer comparer, + [CallerArgumentExpression(nameof(expected))] string? expectedExpression = null, + [CallerArgumentExpression(nameof(comparer))] string? comparerExpression = null) + { + Context.ExpressionBuilder.Append($".Contains({expectedExpression}, {comparerExpression})"); + return new MemoryContainsAssertion(Context, CreateAdapter, expected, comparer); + } + /// /// Asserts that the memory does not contain the expected item. /// @@ -115,6 +128,19 @@ public MemoryDoesNotContainAssertion DoesNotContain( return new MemoryDoesNotContainAssertion(Context, CreateAdapter, expected); } + /// + /// Asserts that the memory does not contain the expected item using a custom equality comparer. + /// + public MemoryDoesNotContainAssertion DoesNotContain( + TItem expected, + IEqualityComparer comparer, + [CallerArgumentExpression(nameof(expected))] string? expectedExpression = null, + [CallerArgumentExpression(nameof(comparer))] string? comparerExpression = null) + { + Context.ExpressionBuilder.Append($".DoesNotContain({expectedExpression}, {comparerExpression})"); + return new MemoryDoesNotContainAssertion(Context, CreateAdapter, expected, comparer); + } + /// /// Gets the count for further numeric assertions. /// diff --git a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet10_0.verified.txt b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet10_0.verified.txt index becf3adaed..ee9184939c 100644 --- a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet10_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet10_0.verified.txt @@ -1187,6 +1187,7 @@ namespace .Conditions where TCollection : . { public HasDistinctItemsAssertion(. context) { } + public HasDistinctItemsAssertion(. context, . comparer) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } @@ -1901,6 +1902,7 @@ namespace .Conditions public class StringEqualsAssertion : . { public StringEqualsAssertion(. context, string? expected) { } + public StringEqualsAssertion(. context, string? expected, . comparer) { } public StringEqualsAssertion(. context, string? expected, comparison) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } @@ -4819,6 +4821,7 @@ namespace .Extensions public static class StringEqualsAssertionExtensions { public static . IsEqualTo(this . source, string? expected, [.("expected")] string? expectedExpression = null) { } + public static . IsEqualTo(this . source, string? expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public static . IsEqualTo(this . source, string? expected, comparison, [.("expected")] string? expectedExpression = null, [.("comparison")] string? comparisonExpression = null) { } } public static class StringIsEmptyAssertionExtensions @@ -5663,6 +5666,7 @@ namespace .Sources public . Any( predicate, [.("predicate")] string? expression = null) { } public . Contains( predicate, [.("predicate")] string? expression = null) { } public . Contains(TItem expected, [.("expected")] string? expression = null) { } + public . Contains(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public . ContainsOnly( predicate, [.("predicate")] string? expression = null) { } public . Count() { } public . Count(<., .?> itemAssertion, [.("itemAssertion")] string? expression = null) { } @@ -5670,6 +5674,7 @@ namespace .Sources public . Count(<., .?> countAssertion, [.("countAssertion")] string? expression = null) { } public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } + public . DoesNotContain(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } protected override string GetExpectation() { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] @@ -5677,6 +5682,7 @@ namespace .Sources [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } public . HasDistinctItems() { } + public . HasDistinctItems(. comparer, [.("comparer")] string? comparerExpression = null) { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } public . IsAssignableTo() { } @@ -5786,9 +5792,11 @@ namespace .Sources public . All( predicate, [.("predicate")] string? expression = null) { } public . Any( predicate, [.("predicate")] string? expression = null) { } public . Contains(TItem expected, [.("expected")] string? expression = null) { } + public . Contains(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public . Count() { } protected abstract . CreateAdapter(TMemory value); public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } + public . DoesNotContain(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } protected override string GetExpectation() { } public . HasDistinctItems() { } public . HasSingleItem() { } diff --git a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt index d3c4bae057..603dcf51d2 100644 --- a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt @@ -1170,6 +1170,7 @@ namespace .Conditions where TCollection : . { public HasDistinctItemsAssertion(. context) { } + public HasDistinctItemsAssertion(. context, . comparer) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } @@ -1884,6 +1885,7 @@ namespace .Conditions public class StringEqualsAssertion : . { public StringEqualsAssertion(. context, string? expected) { } + public StringEqualsAssertion(. context, string? expected, . comparer) { } public StringEqualsAssertion(. context, string? expected, comparison) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } @@ -4769,6 +4771,7 @@ namespace .Extensions public static class StringEqualsAssertionExtensions { public static . IsEqualTo(this . source, string? expected, [.("expected")] string? expectedExpression = null) { } + public static . IsEqualTo(this . source, string? expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public static . IsEqualTo(this . source, string? expected, comparison, [.("expected")] string? expectedExpression = null, [.("comparison")] string? comparisonExpression = null) { } } public static class StringIsEmptyAssertionExtensions @@ -5611,12 +5614,14 @@ namespace .Sources public . Any( predicate, [.("predicate")] string? expression = null) { } public . Contains( predicate, [.("predicate")] string? expression = null) { } public . Contains(TItem expected, [.("expected")] string? expression = null) { } + public . Contains(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public . ContainsOnly( predicate, [.("predicate")] string? expression = null) { } public . Count() { } public . Count(<., .?> itemAssertion, [.("itemAssertion")] string? expression = null) { } public . Count(<., .?> countAssertion, [.("countAssertion")] string? expression = null) { } public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } + public . DoesNotContain(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } protected override string GetExpectation() { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] @@ -5624,6 +5629,7 @@ namespace .Sources [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } public . HasDistinctItems() { } + public . HasDistinctItems(. comparer, [.("comparer")] string? comparerExpression = null) { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } public . IsAssignableTo() { } @@ -5733,9 +5739,11 @@ namespace .Sources public . All( predicate, [.("predicate")] string? expression = null) { } public . Any( predicate, [.("predicate")] string? expression = null) { } public . Contains(TItem expected, [.("expected")] string? expression = null) { } + public . Contains(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public . Count() { } protected abstract . CreateAdapter(TMemory value); public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } + public . DoesNotContain(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } protected override string GetExpectation() { } public . HasDistinctItems() { } public . HasSingleItem() { } diff --git a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt index a47687f281..8e6a186e7d 100644 --- a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt @@ -1187,6 +1187,7 @@ namespace .Conditions where TCollection : . { public HasDistinctItemsAssertion(. context) { } + public HasDistinctItemsAssertion(. context, . comparer) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } @@ -1901,6 +1902,7 @@ namespace .Conditions public class StringEqualsAssertion : . { public StringEqualsAssertion(. context, string? expected) { } + public StringEqualsAssertion(. context, string? expected, . comparer) { } public StringEqualsAssertion(. context, string? expected, comparison) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } @@ -4819,6 +4821,7 @@ namespace .Extensions public static class StringEqualsAssertionExtensions { public static . IsEqualTo(this . source, string? expected, [.("expected")] string? expectedExpression = null) { } + public static . IsEqualTo(this . source, string? expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public static . IsEqualTo(this . source, string? expected, comparison, [.("expected")] string? expectedExpression = null, [.("comparison")] string? comparisonExpression = null) { } } public static class StringIsEmptyAssertionExtensions @@ -5663,6 +5666,7 @@ namespace .Sources public . Any( predicate, [.("predicate")] string? expression = null) { } public . Contains( predicate, [.("predicate")] string? expression = null) { } public . Contains(TItem expected, [.("expected")] string? expression = null) { } + public . Contains(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public . ContainsOnly( predicate, [.("predicate")] string? expression = null) { } public . Count() { } public . Count(<., .?> itemAssertion, [.("itemAssertion")] string? expression = null) { } @@ -5670,6 +5674,7 @@ namespace .Sources public . Count(<., .?> countAssertion, [.("countAssertion")] string? expression = null) { } public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } + public . DoesNotContain(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } protected override string GetExpectation() { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] @@ -5677,6 +5682,7 @@ namespace .Sources [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } public . HasDistinctItems() { } + public . HasDistinctItems(. comparer, [.("comparer")] string? comparerExpression = null) { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } public . IsAssignableTo() { } @@ -5786,9 +5792,11 @@ namespace .Sources public . All( predicate, [.("predicate")] string? expression = null) { } public . Any( predicate, [.("predicate")] string? expression = null) { } public . Contains(TItem expected, [.("expected")] string? expression = null) { } + public . Contains(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public . Count() { } protected abstract . CreateAdapter(TMemory value); public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } + public . DoesNotContain(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } protected override string GetExpectation() { } public . HasDistinctItems() { } public . HasSingleItem() { } diff --git a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.Net4_7.verified.txt b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.Net4_7.verified.txt index a1fe4b0503..dc633b5be8 100644 --- a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.Net4_7.verified.txt +++ b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.Net4_7.verified.txt @@ -1019,6 +1019,7 @@ namespace .Conditions where TCollection : . { public HasDistinctItemsAssertion(. context) { } + public HasDistinctItemsAssertion(. context, . comparer) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } @@ -1687,6 +1688,7 @@ namespace .Conditions public class StringEqualsAssertion : . { public StringEqualsAssertion(. context, string? expected) { } + public StringEqualsAssertion(. context, string? expected, . comparer) { } public StringEqualsAssertion(. context, string? expected, comparison) { } protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } @@ -4194,6 +4196,7 @@ namespace .Extensions public static class StringEqualsAssertionExtensions { public static . IsEqualTo(this . source, string? expected, [.("expected")] string? expectedExpression = null) { } + public static . IsEqualTo(this . source, string? expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public static . IsEqualTo(this . source, string? expected, comparison, [.("expected")] string? expectedExpression = null, [.("comparison")] string? comparisonExpression = null) { } } public static class StringIsEmptyAssertionExtensions @@ -4949,12 +4952,14 @@ namespace .Sources public . Any( predicate, [.("predicate")] string? expression = null) { } public . Contains( predicate, [.("predicate")] string? expression = null) { } public . Contains(TItem expected, [.("expected")] string? expression = null) { } + public . Contains(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } public . ContainsOnly( predicate, [.("predicate")] string? expression = null) { } public . Count() { } public . Count(<., .?> itemAssertion, [.("itemAssertion")] string? expression = null) { } public . Count(<., .?> countAssertion, [.("countAssertion")] string? expression = null) { } public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } + public . DoesNotContain(TItem expected, . comparer, [.("expected")] string? expectedExpression = null, [.("comparer")] string? comparerExpression = null) { } protected override string GetExpectation() { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] @@ -4962,6 +4967,7 @@ namespace .Sources [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } public . HasDistinctItems() { } + public . HasDistinctItems(. comparer, [.("comparer")] string? comparerExpression = null) { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } public . IsAssignableTo() { } 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 f1106c74fd..8386373c06 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 @@ -511,6 +511,13 @@ namespace public static readonly .DefaultExecutor Instance; protected override . ExecuteAsync(<.> action) { } } + public static class Defaults + { + public static readonly ForcefulExitTimeout; + public static readonly HookTimeout; + public static readonly ProcessExitHookDelay; + public static readonly TestTimeout; + } public abstract class DependencyInjectionDataSourceAttribute : .UntypedDataSourceGeneratorAttribute { protected DependencyInjectionDataSourceAttribute() { } @@ -562,6 +569,7 @@ namespace public void SetDisplayName(string displayName) { } public void SetDisplayNameFormatter( formatterType) { } public void SetPriority(. priority) { } + public void SetRetryBackoff(int backoffMs, double backoffMultiplier) { } public void SetRetryLimit(int retryLimit) { } public void SetRetryLimit(int retryCount, <.TestContext, , int, .> shouldRetry) { } } @@ -1138,7 +1146,10 @@ namespace public class RetryAttribute : .TUnitAttribute, .IScopedAttribute, ., . { public RetryAttribute(int times) { } + public int BackoffMs { get; set; } + public double BackoffMultiplier { get; set; } public int Order { get; } + public []? RetryOnExceptionTypes { get; set; } public ScopeType { get; } public int Times { get; } public . OnTestDiscovered(.DiscoveredTestContext context) { } @@ -1407,6 +1418,8 @@ namespace public [] MethodGenericArguments { get; set; } public required .MethodMetadata MethodMetadata { get; set; } public required string MethodName { get; init; } + public int RetryBackoffMs { get; set; } + public double RetryBackoffMultiplier { get; set; } public int RetryLimit { get; set; } public required ReturnType { get; set; } public required object?[] TestClassArguments { get; set; } @@ -2359,6 +2372,8 @@ namespace .Interfaces } public interface ITestConfiguration { + int RetryBackoffMs { get; } + double RetryBackoffMultiplier { get; } int RetryLimit { get; } ? Timeout { get; } }