diff --git a/TUnit.Assertions/Collections/CollectionChecks.cs b/TUnit.Assertions/Collections/CollectionChecks.cs index 86beebae32..9557fe3b38 100644 --- a/TUnit.Assertions/Collections/CollectionChecks.cs +++ b/TUnit.Assertions/Collections/CollectionChecks.cs @@ -160,6 +160,48 @@ public static AssertionResult CheckCount(ICollectionAdapter adapte return AssertionResult.Failed($"received {actual}"); } + /// + /// Checks if the collection has at least the specified minimum number of items. + /// + public static AssertionResult CheckHasAtLeast(ICollectionAdapter adapter, int minCount) + { + var actual = adapter.Count; + if (actual >= minCount) + { + return AssertionResult.Passed; + } + + return AssertionResult.Failed($"found {actual}"); + } + + /// + /// Checks if the collection has at most the specified maximum number of items. + /// + public static AssertionResult CheckHasAtMost(ICollectionAdapter adapter, int maxCount) + { + var actual = adapter.Count; + if (actual <= maxCount) + { + return AssertionResult.Passed; + } + + return AssertionResult.Failed($"found {actual}"); + } + + /// + /// Checks if the collection count is between the specified minimum and maximum (inclusive). + /// + public static AssertionResult CheckHasCountBetween(ICollectionAdapter adapter, int min, int max) + { + var actual = adapter.Count; + if (actual >= min && actual <= max) + { + return AssertionResult.Passed; + } + + return AssertionResult.Failed($"found {actual}"); + } + /// /// Checks if the collection has exactly one item. /// diff --git a/TUnit.Assertions/Conditions/AsyncEnumerableAssertions.cs b/TUnit.Assertions/Conditions/AsyncEnumerableAssertions.cs index 1bd815df6b..5dc50b2980 100644 --- a/TUnit.Assertions/Conditions/AsyncEnumerableAssertions.cs +++ b/TUnit.Assertions/Conditions/AsyncEnumerableAssertions.cs @@ -111,6 +111,84 @@ protected override AssertionResult CheckMaterialized(List items) protected override string GetExpectation() => $"to have {_expected} items"; } +/// +/// Asserts that the async enumerable has at least the specified minimum number of items. +/// +public class AsyncEnumerableHasAtLeastAssertion : AsyncEnumerableAssertionConditionBase +{ + private readonly int _minCount; + + public AsyncEnumerableHasAtLeastAssertion( + AssertionContext> context, + int minCount) + : base(context) + { + _minCount = minCount; + } + + protected override AssertionResult CheckMaterialized(List items) + { + return items.Count >= _minCount + ? AssertionResult.Passed + : AssertionResult.Failed($"found {items.Count} items"); + } + + protected override string GetExpectation() => $"to have at least {_minCount} item(s)"; +} + +/// +/// Asserts that the async enumerable has at most the specified maximum number of items. +/// +public class AsyncEnumerableHasAtMostAssertion : AsyncEnumerableAssertionConditionBase +{ + private readonly int _maxCount; + + public AsyncEnumerableHasAtMostAssertion( + AssertionContext> context, + int maxCount) + : base(context) + { + _maxCount = maxCount; + } + + protected override AssertionResult CheckMaterialized(List items) + { + return items.Count <= _maxCount + ? AssertionResult.Passed + : AssertionResult.Failed($"found {items.Count} items"); + } + + protected override string GetExpectation() => $"to have at most {_maxCount} item(s)"; +} + +/// +/// Asserts that the async enumerable count is between the specified minimum and maximum (inclusive). +/// +public class AsyncEnumerableHasCountBetweenAssertion : AsyncEnumerableAssertionConditionBase +{ + private readonly int _min; + private readonly int _max; + + public AsyncEnumerableHasCountBetweenAssertion( + AssertionContext> context, + int min, + int max) + : base(context) + { + _min = min; + _max = max; + } + + protected override AssertionResult CheckMaterialized(List items) + { + return items.Count >= _min && items.Count <= _max + ? AssertionResult.Passed + : AssertionResult.Failed($"found {items.Count} items"); + } + + protected override string GetExpectation() => $"to have count between {_min} and {_max}"; +} + /// /// Asserts that the async enumerable contains or does not contain the expected item. /// diff --git a/TUnit.Assertions/Conditions/CollectionAssertions.cs b/TUnit.Assertions/Conditions/CollectionAssertions.cs index 66274474b6..f384b00cad 100644 --- a/TUnit.Assertions/Conditions/CollectionAssertions.cs +++ b/TUnit.Assertions/Conditions/CollectionAssertions.cs @@ -230,6 +230,117 @@ protected override Task CheckAsync(EvaluationMetadata $"to have count {_expectedCount}"; } +/// +/// Asserts that a collection has at least the specified minimum number of items (count >= minCount). +/// Delegates to CollectionChecks for the actual logic. +/// +public class CollectionHasAtLeastAssertion : Sources.CollectionAssertionBase + where TCollection : IEnumerable +{ + private readonly int _minCount; + + public CollectionHasAtLeastAssertion( + AssertionContext context, + int minCount) + : base(context) + { + _minCount = minCount; + } + + protected override Task CheckAsync(EvaluationMetadata metadata) + { + if (metadata.Exception != null) + { + return Task.FromResult(AssertionResult.Failed($"threw {metadata.Exception.GetType().Name}")); + } + + if (metadata.Value == null) + { + return Task.FromResult(AssertionResult.Failed("collection was null")); + } + + var adapter = new EnumerableAdapter(metadata.Value); + return Task.FromResult(CollectionChecks.CheckHasAtLeast(adapter, _minCount)); + } + + protected override string GetExpectation() => $"to have at least {_minCount} item(s)"; +} + +/// +/// Asserts that a collection has at most the specified maximum number of items (count <= maxCount). +/// Delegates to CollectionChecks for the actual logic. +/// +public class CollectionHasAtMostAssertion : Sources.CollectionAssertionBase + where TCollection : IEnumerable +{ + private readonly int _maxCount; + + public CollectionHasAtMostAssertion( + AssertionContext context, + int maxCount) + : base(context) + { + _maxCount = maxCount; + } + + protected override Task CheckAsync(EvaluationMetadata metadata) + { + if (metadata.Exception != null) + { + return Task.FromResult(AssertionResult.Failed($"threw {metadata.Exception.GetType().Name}")); + } + + if (metadata.Value == null) + { + return Task.FromResult(AssertionResult.Failed("collection was null")); + } + + var adapter = new EnumerableAdapter(metadata.Value); + return Task.FromResult(CollectionChecks.CheckHasAtMost(adapter, _maxCount)); + } + + protected override string GetExpectation() => $"to have at most {_maxCount} item(s)"; +} + +/// +/// Asserts that a collection count is between the specified minimum and maximum (inclusive). +/// Delegates to CollectionChecks for the actual logic. +/// +public class CollectionHasCountBetweenAssertion : Sources.CollectionAssertionBase + where TCollection : IEnumerable +{ + private readonly int _min; + private readonly int _max; + + public CollectionHasCountBetweenAssertion( + AssertionContext context, + int min, + int max) + : base(context) + { + _min = min; + _max = max; + } + + protected override Task CheckAsync(EvaluationMetadata metadata) + { + if (metadata.Exception != null) + { + return Task.FromResult(AssertionResult.Failed($"threw {metadata.Exception.GetType().Name}")); + } + + if (metadata.Value == null) + { + return Task.FromResult(AssertionResult.Failed("collection was null")); + } + + var adapter = new EnumerableAdapter(metadata.Value); + return Task.FromResult(CollectionChecks.CheckHasCountBetween(adapter, _min, _max)); + } + + protected override string GetExpectation() => $"to have count between {_min} and {_max}"; +} + /// /// Helper for All().Satisfy() pattern - allows custom assertions on all collection items. /// diff --git a/TUnit.Assertions/Sources/AsyncEnumerableAssertionBase.cs b/TUnit.Assertions/Sources/AsyncEnumerableAssertionBase.cs index 2f2652b4f2..bf74e8792c 100644 --- a/TUnit.Assertions/Sources/AsyncEnumerableAssertionBase.cs +++ b/TUnit.Assertions/Sources/AsyncEnumerableAssertionBase.cs @@ -71,6 +71,44 @@ public AsyncEnumerableHasCountAssertion HasCount( return new AsyncEnumerableHasCountAssertion(Context, expected); } + /// + /// Asserts that the async enumerable has at least the specified minimum number of items (count >= minCount). + /// Example: await Assert.That(asyncEnumerable).HasAtLeast(3); + /// + public AsyncEnumerableHasAtLeastAssertion HasAtLeast( + int minCount, + [CallerArgumentExpression(nameof(minCount))] string? expression = null) + { + Context.ExpressionBuilder.Append($".HasAtLeast({expression})"); + return new AsyncEnumerableHasAtLeastAssertion(Context, minCount); + } + + /// + /// Asserts that the async enumerable has at most the specified maximum number of items (count <= maxCount). + /// Example: await Assert.That(asyncEnumerable).HasAtMost(10); + /// + public AsyncEnumerableHasAtMostAssertion HasAtMost( + int maxCount, + [CallerArgumentExpression(nameof(maxCount))] string? expression = null) + { + Context.ExpressionBuilder.Append($".HasAtMost({expression})"); + return new AsyncEnumerableHasAtMostAssertion(Context, maxCount); + } + + /// + /// Asserts that the async enumerable count is between the specified minimum and maximum (inclusive). + /// Example: await Assert.That(asyncEnumerable).HasCountBetween(2, 5); + /// + public AsyncEnumerableHasCountBetweenAssertion HasCountBetween( + int min, + int max, + [CallerArgumentExpression(nameof(min))] string? minExpression = null, + [CallerArgumentExpression(nameof(max))] string? maxExpression = null) + { + Context.ExpressionBuilder.Append($".HasCountBetween({minExpression}, {maxExpression})"); + return new AsyncEnumerableHasCountBetweenAssertion(Context, min, max); + } + /// /// Asserts that the async enumerable contains the expected item. /// Example: await Assert.That(asyncEnumerable).Contains(5); diff --git a/TUnit.Assertions/Sources/CollectionAssertionBase.cs b/TUnit.Assertions/Sources/CollectionAssertionBase.cs index 0a842a097e..0f666e29f3 100644 --- a/TUnit.Assertions/Sources/CollectionAssertionBase.cs +++ b/TUnit.Assertions/Sources/CollectionAssertionBase.cs @@ -273,6 +273,47 @@ public HasSingleItemPredicateAssertion HasSingleItem( return new HasSingleItemPredicateAssertion(Context, predicate, expression ?? "predicate"); } + /// + /// Asserts that the collection has at least the specified minimum number of items (count >= minCount). + /// This instance method enables calling HasAtLeast with proper type inference. + /// Example: await Assert.That(list).HasAtLeast(3); + /// + public CollectionHasAtLeastAssertion HasAtLeast( + int minCount, + [CallerArgumentExpression(nameof(minCount))] string? expression = null) + { + Context.ExpressionBuilder.Append($".HasAtLeast({expression})"); + return new CollectionHasAtLeastAssertion(Context, minCount); + } + + /// + /// Asserts that the collection has at most the specified maximum number of items (count <= maxCount). + /// This instance method enables calling HasAtMost with proper type inference. + /// Example: await Assert.That(list).HasAtMost(10); + /// + public CollectionHasAtMostAssertion HasAtMost( + int maxCount, + [CallerArgumentExpression(nameof(maxCount))] string? expression = null) + { + Context.ExpressionBuilder.Append($".HasAtMost({expression})"); + return new CollectionHasAtMostAssertion(Context, maxCount); + } + + /// + /// Asserts that the collection count is between the specified minimum and maximum (inclusive). + /// This instance method enables calling HasCountBetween with proper type inference. + /// Example: await Assert.That(list).HasCountBetween(2, 5); + /// + public CollectionHasCountBetweenAssertion HasCountBetween( + int min, + int max, + [CallerArgumentExpression(nameof(min))] string? minExpression = null, + [CallerArgumentExpression(nameof(max))] string? maxExpression = null) + { + Context.ExpressionBuilder.Append($".HasCountBetween({minExpression}, {maxExpression})"); + return new CollectionHasCountBetweenAssertion(Context, min, max); + } + /// /// Asserts that the collection contains only distinct (unique) items. /// This instance method enables calling HasDistinctItems with proper type inference. 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..c83fc365c0 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 @@ -500,6 +500,9 @@ namespace .Collections public static . CheckDoesNotContainPredicate(. adapter, predicate) { } public static . CheckDoesNotContainValue(. adapter, TValue value, .? comparer = null) { } public static . CheckDoesNotOverlap(. adapter, . other) { } + public static . CheckHasAtLeast(. adapter, int minCount) { } + public static . CheckHasAtMost(. adapter, int maxCount) { } + public static . CheckHasCountBetween(. adapter, int min, int max) { } public static . CheckHasDistinctItems(. adapter, .? comparer = null) { } public static . CheckHasSingleItem(. adapter) { } public static . CheckHasSingleItemPredicate(. adapter, predicate, out TItem? matchingItem) { } @@ -638,12 +641,30 @@ namespace .Conditions protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasAtLeastAssertion : . + { + public AsyncEnumerableHasAtLeastAssertion(.<.> context, int minCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } + public class AsyncEnumerableHasAtMostAssertion : . + { + public AsyncEnumerableHasAtMostAssertion(.<.> context, int maxCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableHasCountAssertion : . { public AsyncEnumerableHasCountAssertion(.<.> context, int expected) { } protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasCountBetweenAssertion : . + { + public AsyncEnumerableHasCountBetweenAssertion(.<.> context, int min, int max) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableIsEmptyAssertion : . { public AsyncEnumerableIsEmptyAssertion(.<.> context, bool expectEmpty) { } @@ -828,6 +849,27 @@ namespace .Conditions protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } + public class CollectionHasAtLeastAssertion : . + where TCollection : . + { + public CollectionHasAtLeastAssertion(. context, int minCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasAtMostAssertion : . + where TCollection : . + { + public CollectionHasAtMostAssertion(. context, int maxCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasCountBetweenAssertion : . + where TCollection : . + { + public CollectionHasCountBetweenAssertion(. context, int min, int max) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } public class CollectionIsEmptyAssertion : . where TCollection : . { @@ -5619,7 +5661,10 @@ namespace .Sources public . Contains(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } public . DoesNotContain(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } public . HasCount(int expected, [.("expected")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public .> IsAssignableTo() { } public . IsEmpty() { } public .> IsNotAssignableTo() { } @@ -5671,11 +5716,14 @@ namespace .Sources public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] public ..CountWrapper HasCount() { } [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public . HasDistinctItems() { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } 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..7453ce87a5 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 @@ -483,6 +483,9 @@ namespace .Collections public static . CheckDoesNotContainPredicate(. adapter, predicate) { } public static . CheckDoesNotContainValue(. adapter, TValue value, .? comparer = null) { } public static . CheckDoesNotOverlap(. adapter, . other) { } + public static . CheckHasAtLeast(. adapter, int minCount) { } + public static . CheckHasAtMost(. adapter, int maxCount) { } + public static . CheckHasCountBetween(. adapter, int min, int max) { } public static . CheckHasDistinctItems(. adapter, .? comparer = null) { } public static . CheckHasSingleItem(. adapter) { } public static . CheckHasSingleItemPredicate(. adapter, predicate, out TItem? matchingItem) { } @@ -621,12 +624,30 @@ namespace .Conditions protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasAtLeastAssertion : . + { + public AsyncEnumerableHasAtLeastAssertion(.<.> context, int minCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } + public class AsyncEnumerableHasAtMostAssertion : . + { + public AsyncEnumerableHasAtMostAssertion(.<.> context, int maxCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableHasCountAssertion : . { public AsyncEnumerableHasCountAssertion(.<.> context, int expected) { } protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasCountBetweenAssertion : . + { + public AsyncEnumerableHasCountBetweenAssertion(.<.> context, int min, int max) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableIsEmptyAssertion : . { public AsyncEnumerableIsEmptyAssertion(.<.> context, bool expectEmpty) { } @@ -811,6 +832,27 @@ namespace .Conditions protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } + public class CollectionHasAtLeastAssertion : . + where TCollection : . + { + public CollectionHasAtLeastAssertion(. context, int minCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasAtMostAssertion : . + where TCollection : . + { + public CollectionHasAtMostAssertion(. context, int maxCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasCountBetweenAssertion : . + where TCollection : . + { + public CollectionHasCountBetweenAssertion(. context, int min, int max) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } public class CollectionIsEmptyAssertion : . where TCollection : . { @@ -5567,7 +5609,10 @@ namespace .Sources public . Contains(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } public . DoesNotContain(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } public . HasCount(int expected, [.("expected")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public .> IsAssignableTo() { } public . IsEmpty() { } public .> IsNotAssignableTo() { } @@ -5618,11 +5663,14 @@ namespace .Sources public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] public ..CountWrapper HasCount() { } [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public . HasDistinctItems() { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } 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..698502bdab 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 @@ -500,6 +500,9 @@ namespace .Collections public static . CheckDoesNotContainPredicate(. adapter, predicate) { } public static . CheckDoesNotContainValue(. adapter, TValue value, .? comparer = null) { } public static . CheckDoesNotOverlap(. adapter, . other) { } + public static . CheckHasAtLeast(. adapter, int minCount) { } + public static . CheckHasAtMost(. adapter, int maxCount) { } + public static . CheckHasCountBetween(. adapter, int min, int max) { } public static . CheckHasDistinctItems(. adapter, .? comparer = null) { } public static . CheckHasSingleItem(. adapter) { } public static . CheckHasSingleItemPredicate(. adapter, predicate, out TItem? matchingItem) { } @@ -638,12 +641,30 @@ namespace .Conditions protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasAtLeastAssertion : . + { + public AsyncEnumerableHasAtLeastAssertion(.<.> context, int minCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } + public class AsyncEnumerableHasAtMostAssertion : . + { + public AsyncEnumerableHasAtMostAssertion(.<.> context, int maxCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableHasCountAssertion : . { public AsyncEnumerableHasCountAssertion(.<.> context, int expected) { } protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasCountBetweenAssertion : . + { + public AsyncEnumerableHasCountBetweenAssertion(.<.> context, int min, int max) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableIsEmptyAssertion : . { public AsyncEnumerableIsEmptyAssertion(.<.> context, bool expectEmpty) { } @@ -828,6 +849,27 @@ namespace .Conditions protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } + public class CollectionHasAtLeastAssertion : . + where TCollection : . + { + public CollectionHasAtLeastAssertion(. context, int minCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasAtMostAssertion : . + where TCollection : . + { + public CollectionHasAtMostAssertion(. context, int maxCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasCountBetweenAssertion : . + where TCollection : . + { + public CollectionHasCountBetweenAssertion(. context, int min, int max) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } public class CollectionIsEmptyAssertion : . where TCollection : . { @@ -5619,7 +5661,10 @@ namespace .Sources public . Contains(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } public . DoesNotContain(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } public . HasCount(int expected, [.("expected")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public .> IsAssignableTo() { } public . IsEmpty() { } public .> IsNotAssignableTo() { } @@ -5671,11 +5716,14 @@ namespace .Sources public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] public ..CountWrapper HasCount() { } [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public . HasDistinctItems() { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } 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..05d0e27265 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 @@ -442,6 +442,9 @@ namespace .Collections public static . CheckDoesNotContainPredicate(. adapter, predicate) { } public static . CheckDoesNotContainValue(. adapter, TValue value, .? comparer = null) { } public static . CheckDoesNotOverlap(. adapter, . other) { } + public static . CheckHasAtLeast(. adapter, int minCount) { } + public static . CheckHasAtMost(. adapter, int maxCount) { } + public static . CheckHasCountBetween(. adapter, int min, int max) { } public static . CheckHasDistinctItems(. adapter, .? comparer = null) { } public static . CheckHasSingleItem(. adapter) { } public static . CheckHasSingleItemPredicate(. adapter, predicate, out TItem? matchingItem) { } @@ -492,12 +495,30 @@ namespace .Conditions protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasAtLeastAssertion : . + { + public AsyncEnumerableHasAtLeastAssertion(.<.> context, int minCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } + public class AsyncEnumerableHasAtMostAssertion : . + { + public AsyncEnumerableHasAtMostAssertion(.<.> context, int maxCount) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableHasCountAssertion : . { public AsyncEnumerableHasCountAssertion(.<.> context, int expected) { } protected override . CheckMaterialized(. items) { } protected override string GetExpectation() { } } + public class AsyncEnumerableHasCountBetweenAssertion : . + { + public AsyncEnumerableHasCountBetweenAssertion(.<.> context, int min, int max) { } + protected override . CheckMaterialized(. items) { } + protected override string GetExpectation() { } + } public class AsyncEnumerableIsEmptyAssertion : . { public AsyncEnumerableIsEmptyAssertion(.<.> context, bool expectEmpty) { } @@ -678,6 +699,27 @@ namespace .Conditions protected override .<.> CheckAsync(. metadata) { } protected override string GetExpectation() { } } + public class CollectionHasAtLeastAssertion : . + where TCollection : . + { + public CollectionHasAtLeastAssertion(. context, int minCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasAtMostAssertion : . + where TCollection : . + { + public CollectionHasAtMostAssertion(. context, int maxCount) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } + public class CollectionHasCountBetweenAssertion : . + where TCollection : . + { + public CollectionHasCountBetweenAssertion(. context, int min, int max) { } + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } public class CollectionIsEmptyAssertion : . where TCollection : . { @@ -4905,7 +4947,10 @@ namespace .Sources public . Contains(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } public . DoesNotContain(TItem expected, .? comparer = null, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } public . HasCount(int expected, [.("expected")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public .> IsAssignableTo() { } public . IsEmpty() { } public .> IsNotAssignableTo() { } @@ -4956,11 +5001,14 @@ namespace .Sources public . DoesNotContain( predicate, [.("predicate")] string? expression = null) { } public . DoesNotContain(TItem expected, [.("expected")] string? expression = null) { } protected override string GetExpectation() { } + public . HasAtLeast(int minCount, [.("minCount")] string? expression = null) { } + public . HasAtMost(int maxCount, [.("maxCount")] string? expression = null) { } [("Use Count() instead, which provides all numeric assertion methods. Example: Asser" + "(list).Count().IsGreaterThan(5)")] public ..CountWrapper HasCount() { } [("Use Count().IsEqualTo(expectedCount) instead.")] public . HasCount(int expectedCount, [.("expectedCount")] string? expression = null) { } + public . HasCountBetween(int min, int max, [.("min")] string? minExpression = null, [.("max")] string? maxExpression = null) { } public . HasDistinctItems() { } public . HasSingleItem() { } public . HasSingleItem( predicate, [.("predicate")] string? expression = null) { } 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; } }