diff --git a/TUnit.Analyzers.CodeFixers/TwoPhase/XUnitTwoPhaseAnalyzer.cs b/TUnit.Analyzers.CodeFixers/TwoPhase/XUnitTwoPhaseAnalyzer.cs index f6c462c6e8..c33de0bcd1 100644 --- a/TUnit.Analyzers.CodeFixers/TwoPhase/XUnitTwoPhaseAnalyzer.cs +++ b/TUnit.Analyzers.CodeFixers/TwoPhase/XUnitTwoPhaseAnalyzer.cs @@ -625,7 +625,7 @@ private bool IsXUnitAssertion(InvocationExpressionSyntax invocation) var inspectorSummary = string.Join("; ", inspectors); var todoComment = $"// TODO: TUnit migration - Assert.Collection element inspectors were dropped and need manual conversion: {inspectorSummary}"; - return (AssertionConversionKind.Collection, $"await Assert.That({collection}).HasCount({inspectorCount})", true, todoComment); + return (AssertionConversionKind.Collection, $"await Assert.That({collection}).Count().IsEqualTo({inspectorCount})", true, todoComment); } private string? TryConvertActionToPredicate(ExpressionSyntax actionExpression) diff --git a/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs b/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs index 6d63f1763e..cbc2619747 100644 --- a/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs +++ b/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs @@ -1117,7 +1117,7 @@ public async Task MyTest() { var items = new[] { 1, 2, 3 }; // TODO: TUnit migration - Assert.Collection element inspectors were dropped and need manual conversion: [0]: x => Assert.Equal(1, x); [1]: x => Assert.Equal(2, x); [2]: x => Assert.Equal(3, x) - await Assert.That(items).HasCount(3); + await Assert.That(items).Count().IsEqualTo(3); } } """, diff --git a/TUnit.Assertions.SourceGenerator.Tests/AssertionExtensionGeneratorTests.cs b/TUnit.Assertions.SourceGenerator.Tests/AssertionExtensionGeneratorTests.cs index a78e099278..95b8029a5e 100644 --- a/TUnit.Assertions.SourceGenerator.Tests/AssertionExtensionGeneratorTests.cs +++ b/TUnit.Assertions.SourceGenerator.Tests/AssertionExtensionGeneratorTests.cs @@ -13,7 +13,7 @@ public Task NonGenericAssertion() => RunTest( "NonGenericAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsEmpty")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("IsEmpty"); @@ -27,7 +27,7 @@ public Task SingleGenericParameter() => RunTest( "SingleGenericParameterAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsNull")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("IsNull"); @@ -42,7 +42,7 @@ public Task MultipleGenericParameters() => RunTest( "MultipleGenericParametersAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsAssignableTo")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("IsAssignableTo"); @@ -57,7 +57,7 @@ public Task AssertionWithOptionalParameter() => RunTest( "OptionalParameterAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsNotEqualTo")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("IsNotEqualTo"); @@ -72,7 +72,7 @@ public Task AssertionWithGenericConstraints() => RunTest( "GenericConstraintsAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsGreaterThan")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("IsGreaterThan"); @@ -87,7 +87,7 @@ public Task AssertionWithMultipleConstructors() => RunTest( "MultipleConstructorsAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsEqualTo")); await Assert.That(extensionFile).IsNotNull(); // Should generate multiple overloads @@ -103,7 +103,7 @@ public Task AssertionWithNegatedMethod() => RunTest( "NegatedMethodAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsTrue")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("IsTrue"); @@ -118,7 +118,7 @@ public Task AssertionWithDefaultValues() => RunTest( "DefaultValuesAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("= true")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("= true"); @@ -134,7 +134,7 @@ public Task AssertionWithEnumDefault() => RunTest( "EnumDefaultAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("StringComparison")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("StringComparison."); @@ -148,7 +148,7 @@ public Task AssertionWithMultipleParameters() => RunTest( "MultipleParametersAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var extensionFile = generatedFiles.FirstOrDefault(f => f.Contains("IsBetween")); await Assert.That(extensionFile).IsNotNull(); await Assert.That(extensionFile!).Contains("IsBetween"); diff --git a/TUnit.Assertions.SourceGenerator.Tests/DateOnlyAssertionGeneratorTests.cs b/TUnit.Assertions.SourceGenerator.Tests/DateOnlyAssertionGeneratorTests.cs index 8ddfe77f12..548383db98 100644 --- a/TUnit.Assertions.SourceGenerator.Tests/DateOnlyAssertionGeneratorTests.cs +++ b/TUnit.Assertions.SourceGenerator.Tests/DateOnlyAssertionGeneratorTests.cs @@ -13,6 +13,6 @@ public Task GeneratesDateOnlyAssertions() => RunTest( "DateOnlyAssertionExtensions.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(0); + await Assert.That(generatedFiles).Count().IsEqualTo(0); }); } diff --git a/TUnit.Assertions.SourceGenerator.Tests/MethodAssertionGeneratorTests.cs b/TUnit.Assertions.SourceGenerator.Tests/MethodAssertionGeneratorTests.cs index ffa7840ec2..d6d3488c72 100644 --- a/TUnit.Assertions.SourceGenerator.Tests/MethodAssertionGeneratorTests.cs +++ b/TUnit.Assertions.SourceGenerator.Tests/MethodAssertionGeneratorTests.cs @@ -13,7 +13,7 @@ public Task BoolMethod() => RunTest( "BoolMethodAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.FirstOrDefault(f => f.Contains("IsPositive_Assertion")); await Assert.That(mainFile).IsNotNull(); @@ -30,7 +30,7 @@ public Task AssertionResultMethod() => RunTest( "AssertionResultMethodAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.FirstOrDefault(f => f.Contains("IsEven_Assertion")); await Assert.That(mainFile).IsNotNull(); @@ -47,7 +47,7 @@ public Task AsyncBoolMethod() => RunTest( "AsyncBoolAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.FirstOrDefault(f => f.Contains("IsPositiveAsync_Assertion")); await Assert.That(mainFile).IsNotNull(); @@ -63,7 +63,7 @@ public Task AsyncAssertionResultMethod() => RunTest( "AsyncAssertionResultAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.FirstOrDefault(f => f.Contains("IsEvenAsync_Assertion")); await Assert.That(mainFile).IsNotNull(); @@ -79,7 +79,7 @@ public Task GenericMethodWithNonInferableTypeParameter() => RunTest( "GenericMethodWithNonInferableTypeParameter.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.FirstOrDefault(f => f.Contains("IsErrorOfType")); await Assert.That(mainFile).IsNotNull(); @@ -99,7 +99,7 @@ public Task MethodWithComparableConstraint() => RunTest( "MethodWithComparableConstraint.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).IsNotNull(); @@ -122,7 +122,7 @@ public Task MethodWithMultipleConstraints() => RunTest( "MethodWithMultipleConstraints.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).IsNotNull(); @@ -141,7 +141,7 @@ public Task MethodWithReferenceTypeConstraint() => RunTest( "MethodWithReferenceTypeConstraint.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).IsNotNull(); @@ -160,7 +160,7 @@ public Task MethodWithValueTypeConstraint() => RunTest( "MethodWithValueTypeConstraint.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).IsNotNull(); @@ -179,7 +179,7 @@ public Task MethodWithNotNullConstraint() => RunTest( "MethodWithNotNullConstraint.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).IsNotNull(); @@ -210,7 +210,7 @@ public Task MethodWithDefaultValues() => RunTest( "MethodWithDefaultValues.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).IsNotNull(); @@ -229,7 +229,7 @@ public Task RefStructParameter() => RunTest( new RunTestOptions { PreprocessorSymbols = ["NET6_0_OR_GREATER"] }, async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).IsNotNull(); @@ -261,7 +261,7 @@ public Task AssertionResultOfTMethod() => RunTest( "AssertionResultOfTMethodAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).Contains("IEnumerableString_ContainsMatch_String_Assertion"); @@ -282,7 +282,7 @@ public Task AsyncAssertionResultOfTMethod() => RunTest( "AsyncAssertionResultOfTAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.First(); await Assert.That(mainFile).Contains("IEnumerableString_ContainsMatchAsync_String_Assertion"); @@ -303,7 +303,7 @@ public Task ArrayTargetType() => RunTest( "ArrayTargetAssertion.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); var mainFile = generatedFiles.FirstOrDefault(f => f.Contains("ContainsMessage")); await Assert.That(mainFile).IsNotNull(); diff --git a/TUnit.Assertions.SourceGenerator.Tests/RangeAssertionGeneratorTests.cs b/TUnit.Assertions.SourceGenerator.Tests/RangeAssertionGeneratorTests.cs index c2db4ab2e9..0fcc2d3f11 100644 --- a/TUnit.Assertions.SourceGenerator.Tests/RangeAssertionGeneratorTests.cs +++ b/TUnit.Assertions.SourceGenerator.Tests/RangeAssertionGeneratorTests.cs @@ -13,6 +13,6 @@ public Task GeneratesRangeAssertions() => RunTest( "RangeAssertionExtensions.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(0); + await Assert.That(generatedFiles).Count().IsEqualTo(0); }); } diff --git a/TUnit.Assertions.SourceGenerator.Tests/TimeOnlyAssertionGeneratorTests.cs b/TUnit.Assertions.SourceGenerator.Tests/TimeOnlyAssertionGeneratorTests.cs index 89bb05c6fc..f10d965da9 100644 --- a/TUnit.Assertions.SourceGenerator.Tests/TimeOnlyAssertionGeneratorTests.cs +++ b/TUnit.Assertions.SourceGenerator.Tests/TimeOnlyAssertionGeneratorTests.cs @@ -13,6 +13,6 @@ public Task GeneratesTimeOnlyAssertions() => RunTest( "TimeOnlyAssertionExtensions.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount(0); + await Assert.That(generatedFiles).Count().IsEqualTo(0); }); } diff --git a/TUnit.Assertions.Tests/AssertionBuilders/AndAssertionTests.cs b/TUnit.Assertions.Tests/AssertionBuilders/AndAssertionTests.cs index b9619a6063..71518d6187 100644 --- a/TUnit.Assertions.Tests/AssertionBuilders/AndAssertionTests.cs +++ b/TUnit.Assertions.Tests/AssertionBuilders/AndAssertionTests.cs @@ -281,7 +281,7 @@ await Assert.That(value) return _ < 10; }); - await Assert.That(evaluationOrder).HasCount(2); + await Assert.That(evaluationOrder).Count().IsEqualTo(2); await Assert.That(evaluationOrder[0]).IsEqualTo(1); await Assert.That(evaluationOrder[1]).IsEqualTo(2); } @@ -294,7 +294,7 @@ public async Task And_With_Collection_Assertions() await Assert.That(collection) .Contains(3) .And - .HasCount(5); + .Count().IsEqualTo(5); } [Test] @@ -305,6 +305,6 @@ public async Task And_With_String_Assertions() await Assert.That(text) .Contains("Hello") .And - .HasLength(11); + .Length().IsEqualTo(11); } } diff --git a/TUnit.Assertions.Tests/AssertionBuilders/OrAssertionTests.cs b/TUnit.Assertions.Tests/AssertionBuilders/OrAssertionTests.cs index 4eb9e54262..bd15be3323 100644 --- a/TUnit.Assertions.Tests/AssertionBuilders/OrAssertionTests.cs +++ b/TUnit.Assertions.Tests/AssertionBuilders/OrAssertionTests.cs @@ -349,7 +349,7 @@ await Assert.That(value) return _ < 10; // Passes }); - await Assert.That(evaluationOrder).HasCount(2); + await Assert.That(evaluationOrder).Count().IsEqualTo(2); await Assert.That(evaluationOrder[0]).IsEqualTo(1); await Assert.That(evaluationOrder[1]).IsEqualTo(2); } @@ -374,7 +374,7 @@ await Assert.That(value) return _ < 10; }); - await Assert.That(evaluationOrder).HasCount(1); + await Assert.That(evaluationOrder).Count().IsEqualTo(1); await Assert.That(evaluationOrder[0]).IsEqualTo(1); } @@ -386,7 +386,7 @@ public async Task Or_With_Collection_Assertions() await Assert.That(collection) .Contains(5) .Or - .HasCount(3); + .Count().IsEqualTo(3); } [Test] @@ -397,7 +397,7 @@ public async Task Or_With_String_Assertions() await Assert.That(text) .Contains("Goodbye") .Or - .HasLength(11); + .Length(l => l.IsEqualTo(11)); } // [Test] diff --git a/TUnit.Assertions.Tests/Bugs/Issue4446Tests.cs b/TUnit.Assertions.Tests/Bugs/Issue4446Tests.cs index e4cd1d724c..d2ddb29494 100644 --- a/TUnit.Assertions.Tests/Bugs/Issue4446Tests.cs +++ b/TUnit.Assertions.Tests/Bugs/Issue4446Tests.cs @@ -31,7 +31,7 @@ public async Task ICollection_Should_Support_Contains() public async Task ICollection_Should_Support_Count() { ICollection collection = new List { 1, 2, 3 }; - await Assert.That(collection).HasCount().EqualTo(3); + await Assert.That(collection).Count().IsEqualTo(3); } [Test] @@ -73,7 +73,7 @@ public async Task IReadOnlyCollection_Should_Support_Contains() public async Task IReadOnlyCollection_Should_Support_Count() { IReadOnlyCollection collection = new List { 1, 2, 3 }; - await Assert.That(collection).HasCount().EqualTo(3); + await Assert.That(collection).Count().IsEqualTo(3); } [Test] diff --git a/TUnit.Assertions.Tests/DictionaryCollectionTests.cs b/TUnit.Assertions.Tests/DictionaryCollectionTests.cs index 3b1d6adfa5..cc29f16a0b 100644 --- a/TUnit.Assertions.Tests/DictionaryCollectionTests.cs +++ b/TUnit.Assertions.Tests/DictionaryCollectionTests.cs @@ -35,7 +35,7 @@ public async Task Dictionary_HasCount_Works() ["key3"] = 3 }; - await Assert.That(dictionary).HasCount(3); + await Assert.That(dictionary).Count().IsEqualTo(3); } [Test] @@ -130,7 +130,7 @@ await Assert.That(dictionary) // Collection methods work on dictionaries await Assert.That(dictionary) .IsNotEmpty() - .And.HasCount(2) + .And.Count().IsEqualTo(2) .And.Contains(new KeyValuePair("key2", 2)); } @@ -159,7 +159,7 @@ public async Task IReadOnlyDictionary_Collection_Methods_Work() // Collection methods work on IReadOnlyDictionary await Assert.That(dictionary) .IsNotEmpty() - .And.HasCount(2); + .And.Count().IsEqualTo(2); // Dictionary-specific methods also work await Assert.That(dictionary) @@ -612,7 +612,7 @@ public async Task IDictionary_Collection_Methods_Work() // IDictionary should also have access to collection methods await Assert.That(dictionary) .IsNotEmpty() - .And.HasCount(2); + .And.Count().IsEqualTo(2); } [Test] diff --git a/TUnit.Assertions.Tests/ListAssertionTests.cs b/TUnit.Assertions.Tests/ListAssertionTests.cs index ce4feb54c4..7272cbed48 100644 --- a/TUnit.Assertions.Tests/ListAssertionTests.cs +++ b/TUnit.Assertions.Tests/ListAssertionTests.cs @@ -191,7 +191,7 @@ public async Task Test_List_InheritsCollectionMethods() { IList list = new List { 1, 2, 3, 4, 5 }; - await Assert.That(list).HasCount(5); + await Assert.That(list).Count().IsEqualTo(5); await Assert.That(list).All(x => x > 0); await Assert.That(list).Any(x => x == 3); } diff --git a/TUnit.Assertions.Tests/MemberCollectionAssertionTests.cs b/TUnit.Assertions.Tests/MemberCollectionAssertionTests.cs index 5a88568e9f..0ad3e0da01 100644 --- a/TUnit.Assertions.Tests/MemberCollectionAssertionTests.cs +++ b/TUnit.Assertions.Tests/MemberCollectionAssertionTests.cs @@ -15,7 +15,7 @@ public async Task Member_Array_HasCount_Passes() }; await Assert.That(obj) - .Member(x => x.Tags, tags => tags.HasCount(3)); + .Member(x => x.Tags, tags => tags.Count().IsEqualTo(3)); } [Test] @@ -27,10 +27,10 @@ public async Task Member_Array_HasCount_Fails() }; var exception = await Assert.ThrowsAsync(async () => - await Assert.That(obj).Member(x => x.Tags, tags => tags.HasCount(5))); + await Assert.That(obj).Member(x => x.Tags, tags => tags.Count().IsEqualTo(5))); - await Assert.That(exception.Message).Contains("to have count 5"); - await Assert.That(exception.Message).Contains("but received 2"); + await Assert.That(exception.Message).Contains("to have count equal to 5"); + await Assert.That(exception.Message).Contains("received 2"); } [Test] @@ -107,7 +107,7 @@ public async Task Member_Array_Chained_Assertions_Passes() }; await Assert.That(obj) - .Member(x => x.Tags, tags => tags.HasCount(2).And.Contains("tag1").And.Contains("tag2")); + .Member(x => x.Tags, tags => tags.Count().IsEqualTo(2).And.Contains("tag1").And.Contains("tag2")); } [Test] @@ -120,7 +120,7 @@ public async Task Member_Array_Chained_With_Parent_IsNotNull() await Assert.That(obj) .IsNotNull() - .And.Member(x => x.Tags, tags => tags.HasCount(1).And.Contains("tag1")); + .And.Member(x => x.Tags, tags => tags.Count().IsEqualTo(1).And.Contains("tag1")); } [Test] @@ -132,7 +132,7 @@ public async Task Member_List_HasCount_Passes() }; await Assert.That(obj) - .Member(x => x.Items, items => items.HasCount(3)); + .Member(x => x.Items, items => items.Count().IsEqualTo(3)); } [Test] @@ -206,7 +206,7 @@ public async Task Member_Dictionary_HasCount_Passes() }; await Assert.That(obj) - .Member(x => x.Attributes, attrs => attrs.HasCount(2)); + .Member(x => x.Attributes, attrs => attrs.Count().IsEqualTo(2)); } [Test] @@ -269,9 +269,9 @@ public async Task Member_Complex_Chain_Multiple_Collections() await Assert.That(obj) .IsNotNull() - .And.Member(x => x.Tags, tags => tags.HasCount(2).And.Contains("important")) - .And.Member(x => x.Items, items => items.HasCount(3).And.All(x => x > 0)) - .And.Member(x => x.Attributes, attrs => attrs.HasCount(1)); + .And.Member(x => x.Tags, tags => tags.Count().IsEqualTo(2).And.Contains("important")) + .And.Member(x => x.Items, items => items.Count().IsEqualTo(3).And.All(x => x > 0)) + .And.Member(x => x.Attributes, attrs => attrs.Count().IsEqualTo(1)); } [Test] @@ -319,7 +319,7 @@ public async Task Member_IEnumerable_HasCount_Passes() }; await Assert.That(obj) - .Member(x => x.Sequence, seq => seq.HasCount(5)); + .Member(x => x.Sequence, seq => seq.Count().IsEqualTo(5)); } [Test] @@ -333,7 +333,7 @@ public async Task Issue3495_ReportedCase_Array_HasCount_And_Contains() await Assert.That(obj) .IsNotNull() - .And.Member(x => x.Tags, tags => tags.HasCount(2).And.Contains("pile")); + .And.Member(x => x.Tags, tags => tags.Count().IsEqualTo(2).And.Contains("pile")); } [Test] @@ -359,7 +359,7 @@ public async Task Issue3495_Dictionary_ContainsKey() }; await Assert.That(obj) - .Member(x => x.Attributes, attrs => attrs.ContainsKey("status").And.HasCount(1)); + .Member(x => x.Attributes, attrs => attrs.ContainsKey("status").And.Count().IsEqualTo(1)); } private class TestClass diff --git a/TUnit.Assertions.Tests/ParseAssertionTests.cs b/TUnit.Assertions.Tests/ParseAssertionTests.cs index f06e97eb73..bcc605df94 100644 --- a/TUnit.Assertions.Tests/ParseAssertionTests.cs +++ b/TUnit.Assertions.Tests/ParseAssertionTests.cs @@ -59,16 +59,16 @@ await Assert.That("true") [Test] public async Task WhenParsedInto_WithAnd_PreviousAssertion_ShouldFail() { - // HasLength(4) should fail because "123" has length 3 + // Length().IsEqualTo(4) should fail because "123" has length 3 var exception = await Assert.That(async () => { var sut = "123"; await Assert.That(sut) - .HasLength(4) + .Length(l => l.IsEqualTo(4)) .And .WhenParsedInto() .IsEqualTo(123); - }).ThrowsException().And.HasMessageContaining("HasLength(4)"); + }).ThrowsException().And.HasMessageContaining("length"); } [Test] @@ -77,7 +77,7 @@ public async Task WhenParsedInto_WithAnd_PreviousAssertion_ShouldPass() // Both assertions should pass var sut = "123"; await Assert.That(sut) - .HasLength(3) + .Length(l => l.IsEqualTo(3)) .And .WhenParsedInto() .IsEqualTo(123); @@ -86,18 +86,18 @@ await Assert.That(sut) [Test] public async Task WhenParsedInto_WithAnd_MultiplePreviousAssertions_ShouldFail() { - // IsNotEmpty should pass, but HasLength(4) should fail + // IsNotEmpty should pass, but Length(l => l.IsEqualTo(4)) should fail var exception = await Assert.That(async () => { var sut = "123"; await Assert.That(sut) .IsNotEmpty() .And - .HasLength(4) + .Length(l => l.IsEqualTo(4)) .And .WhenParsedInto() .IsGreaterThan(100); - }).ThrowsException().And.HasMessageContaining("HasLength(4)"); + }).ThrowsException().And.HasMessageContaining("length"); } [Test] @@ -106,7 +106,7 @@ public async Task WhenParsedInto_WithAnd_ChainingAfterParse() // Previous assertion should be checked before parsing var sut = "100"; await Assert.That(sut) - .HasLength(3) + .Length(l => l.IsEqualTo(3)) .And .WhenParsedInto() .IsGreaterThan(50) @@ -137,7 +137,7 @@ public async Task WhenParsedInto_WithAnd_ParsedAssertionFails() { var sut = "123"; await Assert.That(sut) - .HasLength(3) + .Length(l => l.IsEqualTo(3)) .And .WhenParsedInto() .IsEqualTo(456); @@ -154,15 +154,15 @@ public async Task WhenParsedInto_AssertMultiple_AllAssertionsChecked() { var sut = "123"; await Assert.That(sut) - .HasLength(4) + .Length(l => l.IsEqualTo(4)) .And .WhenParsedInto() .IsEqualTo(456); } }).ThrowsException(); - // Should have recorded the HasLength failure - await Assert.That(exception.Message).Contains("HasLength"); + // Should have recorded the length assertion failure + await Assert.That(exception.Message).Contains("length"); } [Test] @@ -171,7 +171,7 @@ public async Task WhenParsedInto_ComplexChain_AllChecked() // Complex chain: string assertions, parse, int assertions var sut = "1234"; await Assert.That(sut) - .HasLength(4) + .Length(l => l.IsEqualTo(4)) .And .StartsWith("1") .And @@ -193,7 +193,7 @@ public async Task WhenParsedInto_ComplexChain_MiddleStringAssertionFails() { var sut = "1234"; await Assert.That(sut) - .HasLength(4) + .Length(l => l.IsEqualTo(4)) .And .StartsWith("1") .And diff --git a/TUnit.Assertions.Tests/ReadOnlyListAssertionTests.cs b/TUnit.Assertions.Tests/ReadOnlyListAssertionTests.cs index 45a52256bf..c1d5e3ee28 100644 --- a/TUnit.Assertions.Tests/ReadOnlyListAssertionTests.cs +++ b/TUnit.Assertions.Tests/ReadOnlyListAssertionTests.cs @@ -176,7 +176,7 @@ public async Task Test_IReadOnlyList_Contains_Works() public async Task Test_IReadOnlyList_HasCount_Works() { IReadOnlyList list = new List { 1, 2, 3, 4, 5 }; - await Assert.That(list).HasCount().EqualTo(5); + await Assert.That(list).Count().IsEqualTo(5); } // Chaining tests @@ -222,6 +222,6 @@ public async Task Test_ItemAt_Satisfies_Passes() public async Task Test_LastItem_Satisfies_Passes() { IReadOnlyList list = new List { "a", "bb", "ccc" }; - await Assert.That(list).LastItem().Satisfies(item => item.HasLength(3)); + await Assert.That(list).LastItem().Satisfies(item => item.Length(l => l.IsEqualTo(3))); } } diff --git a/TUnit.Assertions.Tests/SelfTypedCollectionTests.cs b/TUnit.Assertions.Tests/SelfTypedCollectionTests.cs index 5e1a37b0c9..badc170f44 100644 --- a/TUnit.Assertions.Tests/SelfTypedCollectionTests.cs +++ b/TUnit.Assertions.Tests/SelfTypedCollectionTests.cs @@ -39,7 +39,7 @@ await Assert.That(array) .Contains(1) .And.Contains(2) .And.Contains(3) - .And.HasCount(5); + .And.Count().IsEqualTo(5); } [Test] @@ -72,7 +72,7 @@ public async Task Collection_Complex_Chain() await Assert.That(list) .Contains(1) .And.Contains(5) - .And.HasCount(5) + .And.Count().IsEqualTo(5) .And.IsNotEmpty(); } @@ -91,7 +91,7 @@ await Assert.That(collection) .And .Contains("B") .And - .HasCount(3); + .Count().IsEqualTo(3); } [Test] diff --git a/TUnit.Assertions.Tests/SetAssertionTests.cs b/TUnit.Assertions.Tests/SetAssertionTests.cs index d72a329458..9e57aa1cf7 100644 --- a/TUnit.Assertions.Tests/SetAssertionTests.cs +++ b/TUnit.Assertions.Tests/SetAssertionTests.cs @@ -225,7 +225,7 @@ public async Task HashSet_And_Chain_Works() await Assert.That(set) .IsSubsetOf(other) .And.IsNotEmpty() - .And.HasCount(3); + .And.Count().IsEqualTo(3); } [Test] @@ -249,7 +249,7 @@ public async Task HashSet_Inherits_Collection_Methods() // Set should have access to collection methods await Assert.That(set) .IsNotEmpty() - .And.HasCount(3) + .And.Count().IsEqualTo(3) .And.Contains(2); } diff --git a/TUnit.Assertions.Tests/TypeAssertionAmbiguityTests.cs b/TUnit.Assertions.Tests/TypeAssertionAmbiguityTests.cs index bdee6e99ea..29690769a9 100644 --- a/TUnit.Assertions.Tests/TypeAssertionAmbiguityTests.cs +++ b/TUnit.Assertions.Tests/TypeAssertionAmbiguityTests.cs @@ -347,7 +347,7 @@ await Assert.That(obj) .And .IsTypeOf() .And - .HasLength(4); + .Length().IsEqualTo(4); } [Test] @@ -632,7 +632,7 @@ public async Task IsTypeOf_WithCollectionChaining_NoAmbiguity() { List items = ["test", "hello"]; - await Assert.That(items).HasCount(2); + await Assert.That(items).Count().IsEqualTo(2); await Assert.That(items.First()).IsTypeOf(); } @@ -642,7 +642,7 @@ public async Task IsAssignableTo_WithCollectionFiltering_NoAmbiguity() List items = [new Element(), new DerivedElement()]; var derived = items.OfType().ToList(); - await Assert.That(derived).HasCount(1); + await Assert.That(derived).Count().IsEqualTo(1); await Assert.That(derived.First()).IsAssignableTo(); } } diff --git a/TUnit.Assertions.Tests/TypeAssertionTests.cs b/TUnit.Assertions.Tests/TypeAssertionTests.cs index 95a8d269aa..6d8cb5107a 100644 --- a/TUnit.Assertions.Tests/TypeAssertionTests.cs +++ b/TUnit.Assertions.Tests/TypeAssertionTests.cs @@ -504,26 +504,26 @@ public async Task Test_Type_IsNotSerializable() [Test] public async Task IsTypeOf_WithAnd_PreviousAssertion_ShouldFail() { - // HasLength(4) should fail because "123" has length 3 + // Length().IsEqualTo(4) should fail because "123" has length 3 var exception = await Assert.That(async () => { var sut = "123"; await Assert.That(sut) - .HasLength(4) + .Length().IsEqualTo(4) .And .IsTypeOf() .And - .HasLength(3); - }).ThrowsException().And.HasMessageContaining("HasLength(4)"); + .Length().IsEqualTo(3); + }).ThrowsException().And.HasMessageContaining("IsEqualTo(4)"); } [Test] public async Task IsTypeOf_WithAnd_PreviousAssertion_ShouldPass() { - // Both assertions should pass + // Use Length(lambda) to preserve string context for And chaining var sut = "123"; await Assert.That(sut) - .HasLength(3) + .Length(l => l.IsEqualTo(3)) .And .IsTypeOf() .And @@ -540,7 +540,7 @@ await Assert.That(sut) .And .IsTypeOf() .And - .HasLength(4); + .Length().IsEqualTo(4); } [Test] @@ -569,7 +569,7 @@ await Assert.That(sut) .And .IsTypeOf() .And - .HasLength(5) + .Length(l => l.IsEqualTo(5)) .And .StartsWith("h"); } @@ -602,8 +602,8 @@ await Assert.That(sut) .And .IsTypeOf() .And - .HasLength(10); - }).ThrowsException().And.HasMessageContaining("HasLength"); + .Length().IsEqualTo(10); + }).ThrowsException().And.HasMessageContaining("IsEqualTo"); } [Test] @@ -622,7 +622,7 @@ await Assert.That(sut) .And .IsTypeOf() .And - .HasLength(10); + .Length().IsEqualTo(10); } }).ThrowsException(); @@ -640,7 +640,7 @@ await Assert.That(sut) .And .IsTypeOf() .And - .HasLength(5) + .Length(l => l.IsEqualTo(5)) .And .StartsWith("1") .And @@ -658,7 +658,7 @@ await Assert.That(sut) .IsTypeOf>(); // Assert on collection contents separately - await Assert.That((List)sut).HasCount(3); + await Assert.That((List)sut).Count().IsEqualTo(3); } [Test] diff --git a/TUnit.Assertions.Tests/TypeOfTests.cs b/TUnit.Assertions.Tests/TypeOfTests.cs index d5935da8c4..1668b30c94 100644 --- a/TUnit.Assertions.Tests/TypeOfTests.cs +++ b/TUnit.Assertions.Tests/TypeOfTests.cs @@ -241,7 +241,7 @@ public async Task CollectionAssertion_NullableByteArray_CanUseCollectionMethods( byte[]? nullableBytes = new byte[] { 1, 2, 3, 4, 5 }; // Should be able to use collection assertion methods - await Assert.That(nullableBytes).HasCount(5); + await Assert.That(nullableBytes).Count().IsEqualTo(5); await Assert.That(nullableBytes).Contains(3); await Assert.That(nullableBytes).IsInOrder(); @@ -252,7 +252,7 @@ public async Task CollectionAssertion_NullableList_CanUseCollectionMethods() { List? nullableList = new List { 10, 20, 30 }; - await Assert.That(nullableList).HasCount(3); + await Assert.That(nullableList).Count().IsEqualTo(3); await Assert.That(nullableList).Contains(20); await Assert.That(nullableList).IsInOrder(); } @@ -262,7 +262,7 @@ public async Task CollectionAssertion_NullableIEnumerable_CanUseCollectionMethod { IEnumerable? nullableEnumerable = new[] { "apple", "banana", "cherry" }; - await Assert.That(nullableEnumerable).HasCount(3); + await Assert.That(nullableEnumerable).Count().IsEqualTo(3); await Assert.That(nullableEnumerable).Contains("banana"); await Assert.That(nullableEnumerable).IsInOrder(); } diff --git a/TUnit.Assertions/Assertions/Strings/ParseAssertions.cs b/TUnit.Assertions/Assertions/Strings/ParseAssertions.cs index b39dea5aad..83849f77c5 100644 --- a/TUnit.Assertions/Assertions/Strings/ParseAssertions.cs +++ b/TUnit.Assertions/Assertions/Strings/ParseAssertions.cs @@ -231,7 +231,7 @@ public WhenParsedIntoAssertion( : base(new AssertionContext(CreateParsedContext(stringContext.Evaluation, formatProvider), stringContext.ExpressionBuilder)) { // Transfer pending links from string context to handle cross-type chaining - // e.g., Assert.That(str).HasLength(4).And.WhenParsedInto() + // e.g., Assert.That(str).Length().IsEqualTo(4).And.WhenParsedInto() var (pendingAssertion, combinerType) = stringContext.ConsumePendingLink(); if (pendingAssertion != null) { diff --git a/TUnit.Assertions/Conditions/CollectionCountSource.cs b/TUnit.Assertions/Conditions/CollectionCountSource.cs index 547140c5cd..df8ff78b78 100644 --- a/TUnit.Assertions/Conditions/CollectionCountSource.cs +++ b/TUnit.Assertions/Conditions/CollectionCountSource.cs @@ -262,6 +262,7 @@ public class CollectionCountWithInlineAssertionAssertion : C { private readonly Func, Assertion?> _countAssertion; private int _actualCount; + private Assertion? _innerAssertion; internal CollectionCountWithInlineAssertionAssertion( AssertionContext context, @@ -293,30 +294,19 @@ protected override async Task CheckAsync(EvaluationMetadata System.Linq.Enumerable.Count(value) }; - // Create an assertion source for the count and run the inline assertion - var countSource = new ValueAssertion(_actualCount, "count"); - var resultingAssertion = _countAssertion(countSource); - - if (resultingAssertion != null) - { - try - { - await resultingAssertion.AssertAsync(); - return AssertionResult.Passed; - } - catch - { - // Count assertion failed - return AssertionResult.Failed($"count was {_actualCount}"); - } - } - - // Null assertion means no constraint, always pass - return AssertionResult.Passed; + var (result, innerAssertion) = await Helpers.InlineAssertionHelper.ExecuteInlineAssertionAsync( + _actualCount, "count", _countAssertion); + _innerAssertion = innerAssertion; + return result; } protected override string GetExpectation() { + if (_innerAssertion != null) + { + return $"count {_innerAssertion.InternalGetExpectation()}"; + } + return "to satisfy count assertion"; } } diff --git a/TUnit.Assertions/Conditions/Helpers/InlineAssertionHelper.cs b/TUnit.Assertions/Conditions/Helpers/InlineAssertionHelper.cs new file mode 100644 index 0000000000..21a097b2bc --- /dev/null +++ b/TUnit.Assertions/Conditions/Helpers/InlineAssertionHelper.cs @@ -0,0 +1,31 @@ +using TUnit.Assertions.Core; +using TUnit.Assertions.Sources; + +namespace TUnit.Assertions.Conditions.Helpers; + +internal static class InlineAssertionHelper +{ + internal static async Task<(AssertionResult Result, Assertion? InnerAssertion)> ExecuteInlineAssertionAsync( + T actualValue, + string label, + Func, Assertion?> assertion) + { + var source = new ValueAssertion(actualValue, label); + var resultingAssertion = assertion(source); + + if (resultingAssertion == null) + { + return (AssertionResult.Passed, null); + } + + try + { + await resultingAssertion.AssertAsync(); + return (AssertionResult.Passed, resultingAssertion); + } + catch (Exception ex) + { + return (AssertionResult.Failed(ex.Message), resultingAssertion); + } + } +} diff --git a/TUnit.Assertions/Conditions/StringAssertions.cs b/TUnit.Assertions/Conditions/StringAssertions.cs index 8879b37f08..d8cced0c6d 100644 --- a/TUnit.Assertions/Conditions/StringAssertions.cs +++ b/TUnit.Assertions/Conditions/StringAssertions.cs @@ -3,6 +3,7 @@ using TUnit.Assertions.Assertions.Regex; using TUnit.Assertions.Attributes; using TUnit.Assertions.Core; +using TUnit.Assertions.Sources; namespace TUnit.Assertions.Conditions; @@ -517,6 +518,58 @@ protected override Task CheckAsync(EvaluationMetadata m protected override string GetExpectation() => $"to have length {_expectedLength}"; } +/// +/// Asserts on the length of a string using an inline assertion lambda, preserving string context for chaining. +/// Example: await Assert.That(str).Length(l => l.IsEqualTo(5)).And.StartsWith("h"); +/// +public class StringLengthWithInlineAssertionAssertion : Assertion +{ + private readonly Func, Assertion?> _lengthAssertion; + private int _actualLength; + private Assertion? _innerAssertion; + + internal StringLengthWithInlineAssertionAssertion( + AssertionContext context, + Func, Assertion?> lengthAssertion) + : base(context) + { + _lengthAssertion = lengthAssertion; + } + + protected override async Task CheckAsync(EvaluationMetadata metadata) + { + var value = metadata.Value; + var exception = metadata.Exception; + + if (exception != null) + { + return AssertionResult.Failed($"threw {exception.GetType().Name}"); + } + + if (value == null) + { + return AssertionResult.Failed("string was null"); + } + + _actualLength = value.Length; + + var (result, innerAssertion) = await Helpers.InlineAssertionHelper.ExecuteInlineAssertionAsync( + _actualLength, "length", _lengthAssertion); + _innerAssertion = innerAssertion; + return result; + } + + protected override string GetExpectation() + { + if (_innerAssertion != null) + { + return $"length {_innerAssertion.InternalGetExpectation()}"; + } + + return "to satisfy length assertion"; + } +} + /// /// Asserts that a string matches a regular expression pattern and returns a collection of all matches. /// diff --git a/TUnit.Assertions/Conditions/Wrappers/CountWrapper.cs b/TUnit.Assertions/Conditions/Wrappers/CountWrapper.cs deleted file mode 100644 index 2c06445e74..0000000000 --- a/TUnit.Assertions/Conditions/Wrappers/CountWrapper.cs +++ /dev/null @@ -1,288 +0,0 @@ -using System.Collections; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using TUnit.Assertions.Conditions; -using TUnit.Assertions.Core; -using TUnit.Assertions.Extensions; - -namespace TUnit.Assertions.Conditions.Wrappers; - -/// -/// Wrapper for collection count assertions that provides .EqualTo() method. -/// Example: await Assert.That(list).Count().EqualTo(5); -/// -public class CountWrapper : IAssertionSource - where TCollection : IEnumerable -{ - private readonly AssertionContext _context; - - public CountWrapper(AssertionContext context) - { - _context = context; - } - - AssertionContext IAssertionSource.Context => _context; - - /// - /// Not supported on CountWrapper - use IsTypeOf on the assertion source before calling HasCount(). - /// - TypeOfAssertion IAssertionSource.IsTypeOf() - { - throw new NotSupportedException( - "IsTypeOf is not supported after HasCount(). " + - "Use: Assert.That(value).IsTypeOf>().HasCount().EqualTo(5)"); - } - - /// - /// Not supported on CountWrapper - use IsAssignableTo on the assertion source before calling HasCount(). - /// - IsAssignableToAssertion IAssertionSource.IsAssignableTo() - { - throw new NotSupportedException( - "IsAssignableTo is not supported after HasCount(). " + - "Use: Assert.That(value).IsAssignableTo>().HasCount().EqualTo(5)"); - } - - /// - /// Not supported on CountWrapper - use IsNotAssignableTo on the assertion source before calling HasCount(). - /// - IsNotAssignableToAssertion IAssertionSource.IsNotAssignableTo() - { - throw new NotSupportedException( - "IsNotAssignableTo is not supported after HasCount(). " + - "Use: Assert.That(value).IsNotAssignableTo>().HasCount().EqualTo(5)"); - } - - /// - /// Not supported on CountWrapper - use IsAssignableFrom on the assertion source before calling HasCount(). - /// - IsAssignableFromAssertion IAssertionSource.IsAssignableFrom() - { - throw new NotSupportedException( - "IsAssignableFrom is not supported after HasCount(). " + - "Use: Assert.That(value).IsAssignableFrom>().HasCount().EqualTo(5)"); - } - - /// - /// Not supported on CountWrapper - use IsNotAssignableFrom on the assertion source before calling HasCount(). - /// - IsNotAssignableFromAssertion IAssertionSource.IsNotAssignableFrom() - { - throw new NotSupportedException( - "IsNotAssignableFrom is not supported after HasCount(). " + - "Use: Assert.That(value).IsNotAssignableFrom>().HasCount().EqualTo(5)"); - } - - /// - /// Not supported on CountWrapper - use IsNotTypeOf on the assertion source before calling HasCount(). - /// - IsNotTypeOfAssertion IAssertionSource.IsNotTypeOf() - { - throw new NotSupportedException( - "IsNotTypeOf is not supported after HasCount(). " + - "Use: Assert.That(value).IsNotTypeOf>().HasCount().EqualTo(5)"); - } - - /// - /// Asserts that the collection count is equal to the expected count. - /// - public CollectionCountAssertion EqualTo( - int expectedCount, - [CallerArgumentExpression(nameof(expectedCount))] string? expression = null) - { - _context.ExpressionBuilder.Append($".EqualTo({expression})"); - return new CollectionCountAssertion(_context, expectedCount); - } - - /// - /// Asserts that the collection count is greater than or equal to the expected count. - /// - public TValue_IsGreaterThanOrEqualTo_TValue_Assertion GreaterThanOrEqualTo( - int expected, - [CallerArgumentExpression(nameof(expected))] string? expression = null) - { - _context.ExpressionBuilder.Append($".GreaterThanOrEqualTo({expression})"); - // Map context to get the count - var countContext = _context.Map(value => - { - if (value == null) - { - return 0; - } - - if (value is ICollection collection) - { - return collection.Count; - } - - return value.Cast().Count(); - }); - return new TValue_IsGreaterThanOrEqualTo_TValue_Assertion(countContext, expected); - } - - /// - /// Asserts that the collection count is positive (greater than 0). - /// - public TValue_IsGreaterThan_TValue_Assertion Positive() - { - _context.ExpressionBuilder.Append(".Positive()"); - // Map context to get the count - var countContext = _context.Map(value => - { - if (value == null) - { - return 0; - } - - if (value is ICollection collection) - { - return collection.Count; - } - - return value.Cast().Count(); - }); - return new TValue_IsGreaterThan_TValue_Assertion(countContext, 0); - } - - /// - /// Asserts that the collection count is greater than the expected count. - /// - public TValue_IsGreaterThan_TValue_Assertion GreaterThan( - int expected, - [CallerArgumentExpression(nameof(expected))] string? expression = null) - { - _context.ExpressionBuilder.Append($".GreaterThan({expression})"); - // Map context to get the count - var countContext = _context.Map(value => - { - if (value == null) - { - return 0; - } - - if (value is ICollection collection) - { - return collection.Count; - } - - return value.Cast().Count(); - }); - return new TValue_IsGreaterThan_TValue_Assertion(countContext, expected); - } - - /// - /// Asserts that the collection count is less than the expected count. - /// - public TValue_IsLessThan_TValue_Assertion LessThan( - int expected, - [CallerArgumentExpression(nameof(expected))] string? expression = null) - { - _context.ExpressionBuilder.Append($".LessThan({expression})"); - // Map context to get the count - var countContext = _context.Map(value => - { - if (value == null) - { - return 0; - } - - if (value is ICollection collection) - { - return collection.Count; - } - - return value.Cast().Count(); - }); - return new TValue_IsLessThan_TValue_Assertion(countContext, expected); - } - - /// - /// Asserts that the collection count is less than or equal to the expected count. - /// - public TValue_IsLessThanOrEqualTo_TValue_Assertion LessThanOrEqualTo( - int expected, - [CallerArgumentExpression(nameof(expected))] string? expression = null) - { - _context.ExpressionBuilder.Append($".LessThanOrEqualTo({expression})"); - // Map context to get the count - var countContext = _context.Map(value => - { - if (value == null) - { - return 0; - } - - if (value is ICollection collection) - { - return collection.Count; - } - - return value.Cast().Count(); - }); - return new TValue_IsLessThanOrEqualTo_TValue_Assertion(countContext, expected); - } - - /// - /// Asserts that the collection count is between the minimum and maximum values. - /// - public BetweenAssertion Between( - int minimum, - int maximum, - [CallerArgumentExpression(nameof(minimum))] string? minExpression = null, - [CallerArgumentExpression(nameof(maximum))] string? maxExpression = null) - { - _context.ExpressionBuilder.Append($".Between({minExpression}, {maxExpression})"); - // Map context to get the count - var countContext = _context.Map(value => - { - if (value == null) - { - return 0; - } - - if (value is ICollection collection) - { - return collection.Count; - } - - return value.Cast().Count(); - }); - return new BetweenAssertion(countContext, minimum, maximum); - } - - /// - /// Asserts that the collection count is zero (empty collection). - /// - public CollectionCountAssertion Zero() - { - _context.ExpressionBuilder.Append(".Zero()"); - return new CollectionCountAssertion(_context, 0); - } - - /// - /// Asserts that the collection count is not equal to the expected count. - /// - public NotEqualsAssertion NotEqualTo( - int expected, - [CallerArgumentExpression(nameof(expected))] string? expression = null) - { - _context.ExpressionBuilder.Append($".NotEqualTo({expression})"); - // Map context to get the count - var countContext = _context.Map(value => - { - if (value == null) - { - return 0; - } - - if (value is ICollection collection) - { - return collection.Count; - } - - return value.Cast().Count(); - }); - return new NotEqualsAssertion(countContext, expected); - } -} diff --git a/TUnit.Assertions/Conditions/Wrappers/LengthWrapper.cs b/TUnit.Assertions/Conditions/Wrappers/LengthWrapper.cs deleted file mode 100644 index 4518e6068f..0000000000 --- a/TUnit.Assertions/Conditions/Wrappers/LengthWrapper.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Text; -using TUnit.Assertions.Conditions; -using TUnit.Assertions.Core; - -namespace TUnit.Assertions.Conditions.Wrappers; - -/// -/// Wrapper for string length assertions that provides .EqualTo() method. -/// Example: await Assert.That(str).HasLength().EqualTo(5); -/// -public class LengthWrapper : IAssertionSource -{ - private readonly AssertionContext _context; - - public LengthWrapper(AssertionContext context) - { - _context = context; - } - - AssertionContext IAssertionSource.Context => _context; - - /// - /// Not supported on LengthWrapper - use IsTypeOf on the assertion source before calling HasLength(). - /// - TypeOfAssertion IAssertionSource.IsTypeOf() - { - throw new NotSupportedException( - "IsTypeOf is not supported after HasLength(). " + - "Use: Assert.That(value).IsTypeOf().HasLength().EqualTo(5)"); - } - - /// - /// Not supported on LengthWrapper - use IsAssignableTo on the assertion source before calling HasLength(). - /// - IsAssignableToAssertion IAssertionSource.IsAssignableTo() - { - throw new NotSupportedException( - "IsAssignableTo is not supported after HasLength(). " + - "Use: Assert.That(value).IsAssignableTo().HasLength().EqualTo(5)"); - } - - /// - /// Not supported on LengthWrapper - use IsNotAssignableTo on the assertion source before calling HasLength(). - /// - IsNotAssignableToAssertion IAssertionSource.IsNotAssignableTo() - { - throw new NotSupportedException( - "IsNotAssignableTo is not supported after HasLength(). " + - "Use: Assert.That(value).IsNotAssignableTo().HasLength().EqualTo(5)"); - } - - /// - /// Not supported on LengthWrapper - use IsAssignableFrom on the assertion source before calling HasLength(). - /// - IsAssignableFromAssertion IAssertionSource.IsAssignableFrom() - { - throw new NotSupportedException( - "IsAssignableFrom is not supported after HasLength(). " + - "Use: Assert.That(value).IsAssignableFrom().HasLength().EqualTo(5)"); - } - - /// - /// Not supported on LengthWrapper - use IsNotAssignableFrom on the assertion source before calling HasLength(). - /// - IsNotAssignableFromAssertion IAssertionSource.IsNotAssignableFrom() - { - throw new NotSupportedException( - "IsNotAssignableFrom is not supported after HasLength(). " + - "Use: Assert.That(value).IsNotAssignableFrom().HasLength().EqualTo(5)"); - } - - /// - /// Not supported on LengthWrapper - use IsNotTypeOf on the assertion source before calling HasLength(). - /// - IsNotTypeOfAssertion IAssertionSource.IsNotTypeOf() - { - throw new NotSupportedException( - "IsNotTypeOf is not supported after HasLength(). " + - "Use: Assert.That(value).IsNotTypeOf().HasLength().EqualTo(5)"); - } - - /// - /// Asserts that the string length is equal to the expected length. - /// - public StringLengthAssertion EqualTo( - int expectedLength, - [CallerArgumentExpression(nameof(expectedLength))] string? expression = null) - { - _context.ExpressionBuilder.Append($".EqualTo({expression})"); - return new StringLengthAssertion(_context, expectedLength); - } -} diff --git a/TUnit.Assertions/Core/AssertionContext.cs b/TUnit.Assertions/Core/AssertionContext.cs index 7c7157f31b..c70a11c514 100644 --- a/TUnit.Assertions/Core/AssertionContext.cs +++ b/TUnit.Assertions/Core/AssertionContext.cs @@ -58,7 +58,7 @@ public AssertionContext Map(Func, Evaluati var newContext = new AssertionContext(newEvaluation, ExpressionBuilder); // Transfer pending links from source context to handle cross-type chaining - // e.g., Assert.That(str).HasLength(3).And.Match(@"\d+").And.Captured(1) + // e.g., Assert.That(str).Length().IsEqualTo(3).And.Match(@"\d+").And.Captured(1) var (pendingAssertion, combinerType) = ConsumePendingLink(); if (pendingAssertion != null) { diff --git a/TUnit.Assertions/Extensions/Assert.cs b/TUnit.Assertions/Extensions/Assert.cs index 56ef942c59..e5f348f30c 100644 --- a/TUnit.Assertions/Extensions/Assert.cs +++ b/TUnit.Assertions/Extensions/Assert.cs @@ -263,9 +263,9 @@ public static ValueAssertion That( /// /// Creates an assertion for a synchronous function that returns a collection. - /// This overload enables collection-specific assertions (IsEmpty, IsNotEmpty, HasCount, etc.) on lambda-wrapped collections. + /// This overload enables collection-specific assertions (IsEmpty, IsNotEmpty, Count, etc.) on lambda-wrapped collections. /// Example: await Assert.That(() => GetItems()).IsEmpty(); - /// Example: await Assert.That(() => GetItems()).HasCount(5); + /// Example: await Assert.That(() => GetItems()).Count().IsEqualTo(5); /// [OverloadResolutionPriority(1)] public static FuncCollectionAssertion That( @@ -288,9 +288,9 @@ public static FuncAssertion That( /// /// Creates an assertion for an asynchronous function that returns a collection. - /// This overload enables collection-specific assertions (IsEmpty, IsNotEmpty, HasCount, etc.) on async lambda-wrapped collections. + /// This overload enables collection-specific assertions (IsEmpty, IsNotEmpty, Count, etc.) on async lambda-wrapped collections. /// Example: await Assert.That(async () => await GetItemsAsync()).IsEmpty(); - /// Example: await Assert.That(async () => await GetItemsAsync()).HasCount(5); + /// Example: await Assert.That(async () => await GetItemsAsync()).Count().IsEqualTo(5); /// [OverloadResolutionPriority(1)] public static AsyncFuncCollectionAssertion That( diff --git a/TUnit.Assertions/Extensions/AssertionExtensions.cs b/TUnit.Assertions/Extensions/AssertionExtensions.cs index efc3667aba..44a340e649 100644 --- a/TUnit.Assertions/Extensions/AssertionExtensions.cs +++ b/TUnit.Assertions/Extensions/AssertionExtensions.cs @@ -5,7 +5,6 @@ using System.Text.RegularExpressions; using TUnit.Assertions.Chaining; using TUnit.Assertions.Conditions; -using TUnit.Assertions.Conditions.Wrappers; using TUnit.Assertions.Core; using TUnit.Assertions.Sources; @@ -314,10 +313,10 @@ public static MemberAssertionResult Member( /// /// Asserts on a collection member of an object using a lambda selector and assertion lambda. - /// The assertion lambda receives collection assertion methods (HasCount, Contains, IsEmpty, etc.). + /// The assertion lambda receives collection assertion methods (Count, Contains, IsEmpty, etc.). /// Supports type transformations like IsTypeOf within the assertion lambda. /// After the member assertion completes, returns to the parent object context for further chaining. - /// Example: await Assert.That(myObject).Member(x => x.Tags, tags => tags.HasCount(1).And.Contains("value")); + /// Example: await Assert.That(myObject).Member(x => x.Tags, tags => tags.Count().IsEqualTo(1).And.Contains("value")); /// [OverloadResolutionPriority(2)] public static MemberAssertionResult Member( @@ -367,9 +366,9 @@ public static MemberAssertionResult Member /// Asserts on a collection member of an object using a lambda selector and assertion lambda. - /// The assertion lambda receives collection assertion methods (HasCount, Contains, IsEmpty, etc.). + /// The assertion lambda receives collection assertion methods (Count, Contains, IsEmpty, etc.). /// After the member assertion completes, returns to the parent object context for further chaining. - /// Example: await Assert.That(myObject).Member(x => x.Tags, tags => tags.HasCount(1).And.Contains("value")); + /// Example: await Assert.That(myObject).Member(x => x.Tags, tags => tags.Count().IsEqualTo(1).And.Contains("value")); /// [OverloadResolutionPriority(1)] public static MemberAssertionResult Member( @@ -419,9 +418,9 @@ public static MemberAssertionResult Member( /// /// Asserts on a collection member of an object using a lambda selector and assertion lambda. - /// The assertion lambda receives collection assertion methods (HasCount, Contains, IsEmpty, etc.). + /// The assertion lambda receives collection assertion methods (Count, Contains, IsEmpty, etc.). /// After the member assertion completes, returns to the parent object context for further chaining. - /// Example: await Assert.That(myObject).Member(x => x.Tags, tags => tags.HasCount(1).And.Contains("value")); + /// Example: await Assert.That(myObject).Member(x => x.Tags, tags => tags.Count().IsEqualTo(1).And.Contains("value")); /// Note: This overload exists for backward compatibility. For AOT compatibility, use the TTransformed overload instead. /// [OverloadResolutionPriority(1)] @@ -698,29 +697,16 @@ public static StringLengthValueAssertion Length( } /// - /// Returns a wrapper for string length assertions. - /// Example: await Assert.That(str).HasLength().EqualTo(5); + /// Asserts on the length of the string using an inline assertion lambda, preserving string context for chaining. + /// Example: await Assert.That(str).Length(l => l.IsEqualTo(5)).And.StartsWith("h"); /// - [Obsolete("Use Length() instead, which provides all numeric assertion methods. Example: Assert.That(str).Length().IsGreaterThan(5)")] - public static LengthWrapper HasLength( - this IAssertionSource source) - { - source.Context.ExpressionBuilder.Append(".HasLength()"); - return new LengthWrapper(source.Context); - } - - /// - /// Asserts that the string has the expected length. - /// Example: await Assert.That(str).HasLength(5); - /// - [Obsolete("Use Length().IsEqualTo(expectedLength) instead.")] - public static StringLengthAssertion HasLength( + public static StringLengthWithInlineAssertionAssertion Length( this IAssertionSource source, - int expectedLength, - [CallerArgumentExpression(nameof(expectedLength))] string? expression = null) + Func, Assertion?> lengthAssertion, + [CallerArgumentExpression(nameof(lengthAssertion))] string? expression = null) { - source.Context.ExpressionBuilder.Append($".HasLength({expression})"); - return new StringLengthAssertion(source.Context, expectedLength); + source.Context.ExpressionBuilder.Append($".Length({expression})"); + return new StringLengthWithInlineAssertionAssertion(source.Context, lengthAssertion); } /// diff --git a/TUnit.Assertions/Sources/CollectionAssertionBase.cs b/TUnit.Assertions/Sources/CollectionAssertionBase.cs index 31e84310f4..00dc5d3d29 100644 --- a/TUnit.Assertions/Sources/CollectionAssertionBase.cs +++ b/TUnit.Assertions/Sources/CollectionAssertionBase.cs @@ -1,7 +1,6 @@ using System.Collections; using System.Runtime.CompilerServices; using TUnit.Assertions.Conditions; -using TUnit.Assertions.Conditions.Wrappers; using TUnit.Assertions.Core; namespace TUnit.Assertions.Sources; @@ -47,7 +46,7 @@ private protected CollectionAssertionBase( /// /// Asserts that the collection is of the specified type and returns an assertion on the casted value. /// This allows chaining additional assertions on the typed value. - /// Example: await Assert.That((IEnumerable)list).IsTypeOf>().And.HasCount(5); + /// Example: await Assert.That((IEnumerable)list).IsTypeOf>().And.Count().IsEqualTo(5); /// public TypeOfAssertion IsTypeOf() { @@ -82,7 +81,7 @@ public IsNotAssignableFromAssertion IsNotAssignableFrom /// Asserts that the collection is NOT of the specified type. /// This allows chaining additional assertions on the value. - /// Example: await Assert.That((IEnumerable)list).IsNotTypeOf>().And.HasCount(5); + /// Example: await Assert.That((IEnumerable)list).IsNotTypeOf>().And.Count().IsEqualTo(5); /// public IsNotTypeOfAssertion IsNotTypeOf() { @@ -131,32 +130,6 @@ public CollectionContainsPredicateAssertion Contains( return new CollectionContainsPredicateAssertion(Context, predicate); } - /// - /// Asserts that the collection has the expected count. - /// This instance method enables calling HasCount with proper type inference. - /// Example: await Assert.That(list).HasCount(5); - /// - [Obsolete("Use Count().IsEqualTo(expectedCount) instead.")] - public CollectionCountAssertion HasCount( - int expectedCount, - [CallerArgumentExpression(nameof(expectedCount))] string? expression = null) - { - Context.ExpressionBuilder.Append($".HasCount({expression})"); - return new CollectionCountAssertion(Context, expectedCount); - } - - /// - /// Returns a wrapper for fluent count assertions. - /// This enables the pattern: .HasCount().GreaterThan(5) - /// Example: await Assert.That(list).HasCount().EqualTo(5); - /// - [Obsolete("Use Count() instead, which provides all numeric assertion methods. Example: Assert.That(list).Count().IsGreaterThan(5)")] - public CountWrapper HasCount() - { - Context.ExpressionBuilder.Append(".HasCount()"); - return new CountWrapper(Context); - } - /// /// Gets the count of items in the collection for further numeric assertions. /// This enables fluent assertions on the count itself while preserving collection type for chaining. diff --git a/TUnit.Assertions/Sources/DictionaryAssertionBase.cs b/TUnit.Assertions/Sources/DictionaryAssertionBase.cs index a133b1b631..4be375439b 100644 --- a/TUnit.Assertions/Sources/DictionaryAssertionBase.cs +++ b/TUnit.Assertions/Sources/DictionaryAssertionBase.cs @@ -3,7 +3,6 @@ using TUnit.Assertions.Adapters; using TUnit.Assertions.Collections; using TUnit.Assertions.Conditions; -using TUnit.Assertions.Conditions.Wrappers; using TUnit.Assertions.Core; namespace TUnit.Assertions.Sources; diff --git a/TUnit.Assertions/Sources/MutableDictionaryAssertionBase.cs b/TUnit.Assertions/Sources/MutableDictionaryAssertionBase.cs index 7e822e2959..4b35035413 100644 --- a/TUnit.Assertions/Sources/MutableDictionaryAssertionBase.cs +++ b/TUnit.Assertions/Sources/MutableDictionaryAssertionBase.cs @@ -2,7 +2,6 @@ using TUnit.Assertions.Adapters; using TUnit.Assertions.Collections; using TUnit.Assertions.Conditions; -using TUnit.Assertions.Conditions.Wrappers; using TUnit.Assertions.Core; namespace TUnit.Assertions.Sources; diff --git a/TUnit.Assertions/Sources/SetAssertionBase.cs b/TUnit.Assertions/Sources/SetAssertionBase.cs index 8188b8b352..62576cbff1 100644 --- a/TUnit.Assertions/Sources/SetAssertionBase.cs +++ b/TUnit.Assertions/Sources/SetAssertionBase.cs @@ -3,7 +3,6 @@ using TUnit.Assertions.Adapters; using TUnit.Assertions.Collections; using TUnit.Assertions.Conditions; -using TUnit.Assertions.Conditions.Wrappers; using TUnit.Assertions.Core; namespace TUnit.Assertions.Sources; diff --git a/TUnit.Core.SourceGenerator.Tests/Bugs/5118/Tests5118.cs b/TUnit.Core.SourceGenerator.Tests/Bugs/5118/Tests5118.cs index f9eb8ef55d..72664ded69 100644 --- a/TUnit.Core.SourceGenerator.Tests/Bugs/5118/Tests5118.cs +++ b/TUnit.Core.SourceGenerator.Tests/Bugs/5118/Tests5118.cs @@ -11,6 +11,6 @@ public Task Test() => RunTest(Path.Combine(Git.RootDirectory.FullName, "AsyncClassMethodDataSourceTests.cs"), async generatedFiles => { - await Assert.That(generatedFiles).HasCount().EqualTo(1); + await Assert.That(generatedFiles).Count().IsEqualTo(1); }); } diff --git a/TUnit.Core/Contexts/TestRegisteredContext.cs b/TUnit.Core/Contexts/TestRegisteredContext.cs index fb7764bfb1..1ef19e648d 100644 --- a/TUnit.Core/Contexts/TestRegisteredContext.cs +++ b/TUnit.Core/Contexts/TestRegisteredContext.cs @@ -20,10 +20,6 @@ public TestRegisteredContext(TestContext testContext) CustomDisplayName = testContext.CustomDisplayName; } - [Obsolete("Use StateBag property instead.")] - public ConcurrentDictionary ObjectBag => StateBag; - - /// /// Gets the object bag from the underlying TestContext /// diff --git a/TUnit.Core/Interfaces/ITestOutput.cs b/TUnit.Core/Interfaces/ITestOutput.cs index 2546cf1674..74aed40d9b 100644 --- a/TUnit.Core/Interfaces/ITestOutput.cs +++ b/TUnit.Core/Interfaces/ITestOutput.cs @@ -20,27 +20,12 @@ public interface ITestOutput /// TextWriter ErrorOutput { get; } - /// - /// Gets the collection of timing measurements recorded during test execution. - /// Useful for performance profiling and identifying bottlenecks. - /// - [Obsolete("Use OpenTelemetry activity spans instead. Hook timings are now automatically recorded as OTel child spans of the test activity.")] - IReadOnlyCollection Timings { get; } - /// /// Gets the collection of artifacts (files, screenshots, logs) attached to this test. /// Artifacts are preserved after test execution for review and debugging. /// IReadOnlyCollection Artifacts { get; } - /// - /// Records a timing measurement for a specific operation or phase. - /// Thread-safe for concurrent calls. - /// - /// The timing information to record - [Obsolete("Use OpenTelemetry activity spans instead. Hook timings are now automatically recorded as OTel child spans of the test activity.")] - void RecordTiming(Timing timing); - /// /// Attaches an artifact (file, screenshot, log, etc.) to this test. /// Artifacts are preserved after test execution. diff --git a/TUnit.Core/Interfaces/ITestStartEventReceiver.cs b/TUnit.Core/Interfaces/ITestStartEventReceiver.cs index c0964bfb2e..0ef0a48253 100644 --- a/TUnit.Core/Interfaces/ITestStartEventReceiver.cs +++ b/TUnit.Core/Interfaces/ITestStartEventReceiver.cs @@ -37,12 +37,12 @@ namespace TUnit.Core.Interfaces; /// { /// public async ValueTask OnTestStart(TestContext context) /// { -/// context.ObjectBag["StartTime"] = DateTime.UtcNow; +/// context.StateBag["StartTime"] = DateTime.UtcNow; /// } /// /// public async ValueTask OnTestEnd(TestContext context) /// { -/// var start = (DateTime)context.ObjectBag["StartTime"]; +/// var start = (DateTime)context.StateBag["StartTime"]; /// var duration = DateTime.UtcNow - start; /// await context.OutputWriter.WriteLineAsync($"Test took {duration.TotalMilliseconds}ms"); /// } diff --git a/TUnit.Core/TestBuilderContext.cs b/TUnit.Core/TestBuilderContext.cs index 6d4798dcbc..e6dbbdc43f 100644 --- a/TUnit.Core/TestBuilderContext.cs +++ b/TUnit.Core/TestBuilderContext.cs @@ -25,9 +25,6 @@ public static TestBuilderContext? Current /// public string DefinitionId => _definitionId ??= Guid.NewGuid().ToString(); - [Obsolete("Use StateBag property instead.")] - public ConcurrentDictionary ObjectBag => StateBag; - private ConcurrentDictionary? _stateBag; private TestContextEvents? _events; diff --git a/TUnit.Core/TestContext.Output.cs b/TUnit.Core/TestContext.Output.cs index afde0f3f6e..ac94e3bdc2 100644 --- a/TUnit.Core/TestContext.Output.cs +++ b/TUnit.Core/TestContext.Output.cs @@ -4,15 +4,19 @@ namespace TUnit.Core; +internal record TimingEntry(string StepName, DateTimeOffset Start, DateTimeOffset End) +{ + public TimeSpan Duration => End - Start; +} + /// /// Test output capture and artifact management /// Implements interface /// public partial class TestContext { -#pragma warning disable CS0618 // Obsolete Timing API — internal backing for interface implementation // Internal backing fields and properties - internal ConcurrentBag Timings { get; } = []; + internal ConcurrentBag Timings { get; } = []; private readonly ConcurrentBag _artifactsBag = new(); internal IReadOnlyList Artifacts => _artifactsBag.ToArray(); @@ -20,17 +24,8 @@ public partial class TestContext // Explicit interface implementations for ITestOutput TextWriter ITestOutput.StandardOutput => OutputWriter; TextWriter ITestOutput.ErrorOutput => ErrorOutputWriter; - IReadOnlyCollection ITestOutput.Timings => Timings; -#pragma warning restore CS0618 IReadOnlyCollection ITestOutput.Artifacts => Artifacts; -#pragma warning disable CS0618 // Obsolete Timing API — internal backing for interface implementation - void ITestOutput.RecordTiming(Timing timing) - { - Timings.Add(timing); - } -#pragma warning restore CS0618 - void ITestOutput.AttachArtifact(Artifact artifact) { _artifactsBag.Add(artifact); diff --git a/TUnit.Core/Timing.cs b/TUnit.Core/Timing.cs deleted file mode 100644 index 096c9f6a78..0000000000 --- a/TUnit.Core/Timing.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TUnit.Core; - -[Obsolete("Use OpenTelemetry activity spans instead. Hook timings are now automatically recorded as OTel child spans of the test activity.")] -public record Timing(string StepName, DateTimeOffset Start, DateTimeOffset End) -{ - public TimeSpan Duration => End - Start; -} diff --git a/TUnit.Engine/Extensions/TestExtensions.cs b/TUnit.Engine/Extensions/TestExtensions.cs index 602a450218..f7a75b01b8 100644 --- a/TUnit.Engine/Extensions/TestExtensions.cs +++ b/TUnit.Engine/Extensions/TestExtensions.cs @@ -291,7 +291,6 @@ private static bool IsTrxEnabled(TestContext testContext) return _cachedIsTrxEnabled.Value; } -#pragma warning disable CS0618 // Obsolete Timing API — still needed for TimingProperty reporting private static TimingProperty GetTimingProperty(TestContext testContext, DateTimeOffset overallStart) { if (overallStart == default(DateTimeOffset)) @@ -310,7 +309,6 @@ private static TimingProperty GetTimingProperty(TestContext testContext, DateTim return new TimingProperty(new TimingInfo(overallStart, end, end - overallStart), stepTimings); } -#pragma warning restore CS0618 private static IEnumerable GetTrxMessages(TestContext testContext, string? standardOutput, string? standardError) { diff --git a/TUnit.Engine/Services/TestExecution/RetryHelper.cs b/TUnit.Engine/Services/TestExecution/RetryHelper.cs index 7352cba6cb..cd8a84a76f 100644 --- a/TUnit.Engine/Services/TestExecution/RetryHelper.cs +++ b/TUnit.Engine/Services/TestExecution/RetryHelper.cs @@ -49,9 +49,7 @@ public static async Task ExecuteWithRetry(TestContext testContext, Func stringContext) { } } + public class StringLengthWithInlineAssertionAssertion : . + { + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } public class StringMatchesAssertion : .<..RegexMatchCollection> { public StringMatchesAssertion(. context, . regex) { } @@ -2358,28 +2363,6 @@ namespace . public static . IsValidJsonObject(this string value) { } } } -namespace . -{ - public class CountWrapper : ., . - where TCollection : . - { - public CountWrapper(. context) { } - public . Between(int minimum, int maximum, [.("minimum")] string? minExpression = null, [.("maximum")] string? maxExpression = null) { } - public . EqualTo(int expectedCount, [.("expectedCount")] string? expression = null) { } - public ._IsGreaterThan_TValue_Assertion GreaterThan(int expected, [.("expected")] string? expression = null) { } - public ._IsGreaterThanOrEqualTo_TValue_Assertion GreaterThanOrEqualTo(int expected, [.("expected")] string? expression = null) { } - public ._IsLessThan_TValue_Assertion LessThan(int expected, [.("expected")] string? expression = null) { } - public ._IsLessThanOrEqualTo_TValue_Assertion LessThanOrEqualTo(int expected, [.("expected")] string? expression = null) { } - public . NotEqualTo(int expected, [.("expected")] string? expression = null) { } - public ._IsGreaterThan_TValue_Assertion Positive() { } - public . Zero() { } - } - public class LengthWrapper : ., . - { - public LengthWrapper(. context) { } - public . EqualTo(int expectedLength, [.("expectedLength")] string? expression = null) { } - } -} namespace .Core { public class AndContinuation : . { } @@ -2620,11 +2603,6 @@ namespace .Extensions public static . CompletesWithin(this . source, timeout, [.("timeout")] string? expression = null) { } public static . EqualTo(this . source, TValue? expected, [.("expected")] string? expression = null) { } public static . Eventually(this . source, <., .> assertionBuilder, timeout, ? pollingInterval = default, [.("timeout")] string? timeoutExpression = null, [.("pollingInterval")] string? pollingIntervalExpression = null) { } - [("Use Length() instead, which provides all numeric assertion methods. Example: Asse" + - "(str).Length().IsGreaterThan(5)")] - public static ..LengthWrapper HasLength(this . source) { } - [("Use Length().IsEqualTo(expectedLength) instead.")] - public static . HasLength(this . source, int expectedLength, [.("expectedLength")] string? expression = null) { } public static . HasMessage(this . source, string expectedMessage, [.("expectedMessage")] string? expression = null) where TException : { } public static . HasMessage(this . source, string expectedMessage, comparison, [.("expectedMessage")] string? expression = null) @@ -2679,6 +2657,7 @@ namespace .Extensions public static ._IsGreaterThan_TValue_Assertion IsPositive(this . source) where TValue : struct, { } public static . Length(this . source) { } + public static . Length(this . source, <., .?> lengthAssertion, [.("lengthAssertion")] string? expression = null) { } [.(1)] public static . Member(this . source, .<>> memberSelector, <.<., TItem>, .<.>> assertions) { } [.("Uses reflection for legacy compatibility. For AOT compatibility, use the Member 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 . HasDistinctItems(. comparer, [.("comparer")] string? comparerExpression = 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 8e96e7b507..74a873ff56 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 @@ -2031,6 +2031,11 @@ namespace .Conditions { public StringLengthValueAssertion(. stringContext) { } } + public class StringLengthWithInlineAssertionAssertion : . + { + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } public class StringMatchesAssertion : .<..RegexMatchCollection> { public StringMatchesAssertion(. context, . regex) { } @@ -2337,28 +2342,6 @@ namespace . public static . IsValidJsonObject(this string value) { } } } -namespace . -{ - public class CountWrapper : ., . - where TCollection : . - { - public CountWrapper(. context) { } - public . Between(int minimum, int maximum, [.("minimum")] string? minExpression = null, [.("maximum")] string? maxExpression = null) { } - public . EqualTo(int expectedCount, [.("expectedCount")] string? expression = null) { } - public ._IsGreaterThan_TValue_Assertion GreaterThan(int expected, [.("expected")] string? expression = null) { } - public ._IsGreaterThanOrEqualTo_TValue_Assertion GreaterThanOrEqualTo(int expected, [.("expected")] string? expression = null) { } - public ._IsLessThan_TValue_Assertion LessThan(int expected, [.("expected")] string? expression = null) { } - public ._IsLessThanOrEqualTo_TValue_Assertion LessThanOrEqualTo(int expected, [.("expected")] string? expression = null) { } - public . NotEqualTo(int expected, [.("expected")] string? expression = null) { } - public ._IsGreaterThan_TValue_Assertion Positive() { } - public . Zero() { } - } - public class LengthWrapper : ., . - { - public LengthWrapper(. context) { } - public . EqualTo(int expectedLength, [.("expectedLength")] string? expression = null) { } - } -} namespace .Core { public class AndContinuation : . { } @@ -2599,11 +2582,6 @@ namespace .Extensions public static . CompletesWithin(this . source, timeout, [.("timeout")] string? expression = null) { } public static . EqualTo(this . source, TValue? expected, [.("expected")] string? expression = null) { } public static . Eventually(this . source, <., .> assertionBuilder, timeout, ? pollingInterval = default, [.("timeout")] string? timeoutExpression = null, [.("pollingInterval")] string? pollingIntervalExpression = null) { } - [("Use Length() instead, which provides all numeric assertion methods. Example: Asse" + - "(str).Length().IsGreaterThan(5)")] - public static ..LengthWrapper HasLength(this . source) { } - [("Use Length().IsEqualTo(expectedLength) instead.")] - public static . HasLength(this . source, int expectedLength, [.("expectedLength")] string? expression = null) { } public static . HasMessage(this . source, string expectedMessage, [.("expectedMessage")] string? expression = null) where TException : { } public static . HasMessage(this . source, string expectedMessage, comparison, [.("expectedMessage")] string? expression = null) @@ -2658,6 +2636,7 @@ namespace .Extensions public static ._IsGreaterThan_TValue_Assertion IsPositive(this . source) where TValue : struct, { } public static . Length(this . source) { } + public static . Length(this . source, <., .?> lengthAssertion, [.("lengthAssertion")] string? expression = null) { } public static . Member(this . source, .<>> memberSelector, <.<., TItem>, .<.>> assertions) { } [.("Uses reflection for legacy compatibility. For AOT compatibility, use the Member overload with strongly-typed assertions.")] @@ -6061,11 +6040,6 @@ namespace .Sources 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 . HasDistinctItems(. comparer, [.("comparer")] string? comparerExpression = 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 130da6da01..e3de133c4f 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 @@ -2048,6 +2048,11 @@ namespace .Conditions { public StringLengthValueAssertion(. stringContext) { } } + public class StringLengthWithInlineAssertionAssertion : . + { + protected override .<.> CheckAsync(. metadata) { } + protected override string GetExpectation() { } + } public class StringMatchesAssertion : .<..RegexMatchCollection> { public StringMatchesAssertion(. context, . regex) { } @@ -2358,28 +2363,6 @@ namespace . public static . IsValidJsonObject(this string value) { } } } -namespace . -{ - public class CountWrapper : ., . - where TCollection : . - { - public CountWrapper(. context) { } - public . Between(int minimum, int maximum, [.("minimum")] string? minExpression = null, [.("maximum")] string? maxExpression = null) { } - public . EqualTo(int expectedCount, [.("expectedCount")] string? expression = null) { } - public ._IsGreaterThan_TValue_Assertion GreaterThan(int expected, [.("expected")] string? expression = null) { } - public ._IsGreaterThanOrEqualTo_TValue_Assertion GreaterThanOrEqualTo(int expected, [.("expected")] string? expression = null) { } - public ._IsLessThan_TValue_Assertion LessThan(int expected, [.("expected")] string? expression = null) { } - public ._IsLessThanOrEqualTo_TValue_Assertion LessThanOrEqualTo(int expected, [.("expected")] string? expression = null) { } - public . NotEqualTo(int expected, [.("expected")] string? expression = null) { } - public ._IsGreaterThan_TValue_Assertion Positive() { } - public . Zero() { } - } - public class LengthWrapper : ., . - { - public LengthWrapper(. context) { } - public . EqualTo(int expectedLength, [.("expectedLength")] string? expression = null) { } - } -} namespace .Core { public class AndContinuation : . { } @@ -2620,11 +2603,6 @@ namespace .Extensions public static . CompletesWithin(this . source, timeout, [.("timeout")] string? expression = null) { } public static . EqualTo(this . source, TValue? expected, [.("expected")] string? expression = null) { } public static . Eventually(this . source, <., .> assertionBuilder, timeout, ? pollingInterval = default, [.("timeout")] string? timeoutExpression = null, [.("pollingInterval")] string? pollingIntervalExpression = null) { } - [("Use Length() instead, which provides all numeric assertion methods. Example: Asse" + - "(str).Length().IsGreaterThan(5)")] - public static ..LengthWrapper HasLength(this . source) { } - [("Use Length().IsEqualTo(expectedLength) instead.")] - public static . HasLength(this . source, int expectedLength, [.("expectedLength")] string? expression = null) { } public static . HasMessage(this . source, string expectedMessage, [.("expectedMessage")] string? expression = null) where TException : { } public static . HasMessage(this . source, string expectedMessage, comparison, [.("expectedMessage")] string? expression = null) @@ -2679,6 +2657,7 @@ namespace .Extensions public static ._IsGreaterThan_TValue_Assertion IsPositive(this . source) where TValue : struct, { } public static . Length(this . source) { } + public static . Length(this . source, <., .?> lengthAssertion, [.("lengthAssertion")] string? expression = null) { } [.(1)] public static . Member(this . source, .<>> memberSelector, <.<., TItem>, .<.>> assertions) { } [.("Uses reflection for legacy compatibility. For AOT compatibility, use the Member 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 . HasDistinctItems(. comparer, [.("comparer")] string? comparerExpression = null) { } 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 a750c49483..82d6d29bc4 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 @@ -1340,8 +1340,6 @@ namespace public .IDataSourceAttribute? DataSourceAttribute { get; set; } public string DefinitionId { get; } public .TestContextEvents Events { get; set; } - [("Use StateBag property instead.")] - public . ObjectBag { get; } public . StateBag { get; set; } public required .MethodMetadata TestMetadata { get; init; } public static .TestBuilderContext? Current { get; } @@ -1632,8 +1630,6 @@ namespace public TestRegisteredContext(.TestContext testContext) { } public string? CustomDisplayName { get; } public .DiscoveredTest DiscoveredTest { get; set; } - [("Use StateBag property instead.")] - public . ObjectBag { get; } public . StateBag { get; } public .TestContext TestContext { get; } public .TestDetails TestDetails { get; } @@ -1704,16 +1700,6 @@ namespace public . OnHookRegistered(.HookRegisteredContext context) { } public . OnTestDiscovered(.DiscoveredTestContext context) { } } - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - public class Timing : <.Timing> - { - public Timing(string StepName, Start, End) { } - public Duration { get; } - public End { get; init; } - public Start { get; init; } - public string StepName { get; init; } - } public sealed class TypeArrayComparer : .<[]> { public static readonly .TypeArrayComparer Instance; @@ -2632,16 +2618,10 @@ namespace .Interfaces .<.Artifact> Artifacts { get; } .TextWriter ErrorOutput { get; } .TextWriter StandardOutput { get; } - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - .<.Timing> Timings { get; } void AttachArtifact(.Artifact artifact); void AttachArtifact(string filePath, string? displayName = null, string? description = null); string GetErrorOutput(); string GetStandardOutput(); - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - void RecordTiming(.Timing timing); void WriteError(string message); void WriteLine(string message); } 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 348b7a337e..1d18788c92 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 @@ -1340,8 +1340,6 @@ namespace public .IDataSourceAttribute? DataSourceAttribute { get; set; } public string DefinitionId { get; } public .TestContextEvents Events { get; set; } - [("Use StateBag property instead.")] - public . ObjectBag { get; } public . StateBag { get; set; } public required .MethodMetadata TestMetadata { get; init; } public static .TestBuilderContext? Current { get; } @@ -1632,8 +1630,6 @@ namespace public TestRegisteredContext(.TestContext testContext) { } public string? CustomDisplayName { get; } public .DiscoveredTest DiscoveredTest { get; set; } - [("Use StateBag property instead.")] - public . ObjectBag { get; } public . StateBag { get; } public .TestContext TestContext { get; } public .TestDetails TestDetails { get; } @@ -1704,16 +1700,6 @@ namespace public . OnHookRegistered(.HookRegisteredContext context) { } public . OnTestDiscovered(.DiscoveredTestContext context) { } } - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - public class Timing : <.Timing> - { - public Timing(string StepName, Start, End) { } - public Duration { get; } - public End { get; init; } - public Start { get; init; } - public string StepName { get; init; } - } public sealed class TypeArrayComparer : .<[]> { public static readonly .TypeArrayComparer Instance; @@ -2632,16 +2618,10 @@ namespace .Interfaces .<.Artifact> Artifacts { get; } .TextWriter ErrorOutput { get; } .TextWriter StandardOutput { get; } - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - .<.Timing> Timings { get; } void AttachArtifact(.Artifact artifact); void AttachArtifact(string filePath, string? displayName = null, string? description = null); string GetErrorOutput(); string GetStandardOutput(); - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - void RecordTiming(.Timing timing); void WriteError(string message); void WriteLine(string message); } 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 f3a7961d03..efdbcc7fdc 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 @@ -1340,8 +1340,6 @@ namespace public .IDataSourceAttribute? DataSourceAttribute { get; set; } public string DefinitionId { get; } public .TestContextEvents Events { get; set; } - [("Use StateBag property instead.")] - public . ObjectBag { get; } public . StateBag { get; set; } public required .MethodMetadata TestMetadata { get; init; } public static .TestBuilderContext? Current { get; } @@ -1632,8 +1630,6 @@ namespace public TestRegisteredContext(.TestContext testContext) { } public string? CustomDisplayName { get; } public .DiscoveredTest DiscoveredTest { get; set; } - [("Use StateBag property instead.")] - public . ObjectBag { get; } public . StateBag { get; } public .TestContext TestContext { get; } public .TestDetails TestDetails { get; } @@ -1704,16 +1700,6 @@ namespace public . OnHookRegistered(.HookRegisteredContext context) { } public . OnTestDiscovered(.DiscoveredTestContext context) { } } - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - public class Timing : <.Timing> - { - public Timing(string StepName, Start, End) { } - public Duration { get; } - public End { get; init; } - public Start { get; init; } - public string StepName { get; init; } - } public sealed class TypeArrayComparer : .<[]> { public static readonly .TypeArrayComparer Instance; @@ -2632,16 +2618,10 @@ namespace .Interfaces .<.Artifact> Artifacts { get; } .TextWriter ErrorOutput { get; } .TextWriter StandardOutput { get; } - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - .<.Timing> Timings { get; } void AttachArtifact(.Artifact artifact); void AttachArtifact(string filePath, string? displayName = null, string? description = null); string GetErrorOutput(); string GetStandardOutput(); - [("Use OpenTelemetry activity spans instead. Hook timings are now automatically reco" + - "rded as OTel child spans of the test activity.")] - void RecordTiming(.Timing timing); void WriteError(string message); void WriteLine(string message); } diff --git a/TUnit.RpcTests/Tests.cs b/TUnit.RpcTests/Tests.cs index 90a3d67bd4..de0411155a 100644 --- a/TUnit.RpcTests/Tests.cs +++ b/TUnit.RpcTests/Tests.cs @@ -182,7 +182,7 @@ private async Task RunTestsAsync(CancellationToken cancellationToken, Func= 3400)"); - await Assert.That(originalDiscovered).HasCount().GreaterThanOrEqualTo(3400); + await Assert.That(originalDiscovered).Count().IsGreaterThanOrEqualTo(3400); } Console.WriteLine("[RPC Test] Sending exit command to test host..."); diff --git a/TUnit.TestProject/Bugs/1939/Tests.cs b/TUnit.TestProject/Bugs/1939/Tests.cs index ae41010133..65cccb3725 100644 --- a/TUnit.TestProject/Bugs/1939/Tests.cs +++ b/TUnit.TestProject/Bugs/1939/Tests.cs @@ -45,8 +45,8 @@ public static async Task AssertAllDataClassesDisposed(TestSessionContext context using var _ = Assert.Multiple(); - await Assert.That(dataClasses).HasCount().EqualTo(6); - await Assert.That(dataClasses.Where(x => x.Disposed)).HasCount().EqualTo(6); + await Assert.That(dataClasses).Count().IsEqualTo(6); + await Assert.That(dataClasses.Where(x => x.Disposed)).Count().IsEqualTo(6); foreach (var test in tests.Where(x => x.Execution.Result != null)) { diff --git a/TUnit.TestProject/Bugs/2481/Tests.cs b/TUnit.TestProject/Bugs/2481/Tests.cs index 341dea72e9..4839b265cc 100644 --- a/TUnit.TestProject/Bugs/2481/Tests.cs +++ b/TUnit.TestProject/Bugs/2481/Tests.cs @@ -15,7 +15,7 @@ public async Task Test() var array = properties["Group"].ToArray(); - await Assert.That(array).HasCount().EqualTo(3); + await Assert.That(array).Count().IsEqualTo(3); await Assert.That(array).Contains((string x) => x == "Bugs"); await Assert.That(array).Contains((string x) => x == "2481"); await Assert.That(array).Contains((string x) => x == "TUnit"); diff --git a/TUnit.TestProject/Bugs/3627/FilteredDependencyTests.cs b/TUnit.TestProject/Bugs/3627/FilteredDependencyTests.cs index 85ff6ff4b6..a45e9319e5 100644 --- a/TUnit.TestProject/Bugs/3627/FilteredDependencyTests.cs +++ b/TUnit.TestProject/Bugs/3627/FilteredDependencyTests.cs @@ -29,7 +29,7 @@ public async Task DependentTest() // When filtering to run only this test, BaseTest should also execute var dependencies = TestContext.Current!.Dependencies.GetTests(nameof(BaseTest)); - await Assert.That(dependencies).HasCount().EqualTo(1); + await Assert.That(dependencies).Count().IsEqualTo(1); await Assert.That(dependencies[0]).IsNotNull(); // Verify the dependency actually executed by checking its StateBag diff --git a/TUnit.TestProject/Bugs/3627/Tests.cs b/TUnit.TestProject/Bugs/3627/Tests.cs index 22ec53a60c..ef8f1f20bc 100644 --- a/TUnit.TestProject/Bugs/3627/Tests.cs +++ b/TUnit.TestProject/Bugs/3627/Tests.cs @@ -24,7 +24,7 @@ public async Task SecondTest_AccessDependentData() { var dependentTests = TestContext.Current!.Dependencies.GetTests(nameof(FirstTest_SetupData)); - await Assert.That(dependentTests).HasCount().EqualTo(1); + await Assert.That(dependentTests).Count().IsEqualTo(1); var firstTestContext = dependentTests[0]; diff --git a/TUnit.TestProject/Bugs/3992/InstanceMethodDataSourceWithAsyncInitializerTests.cs b/TUnit.TestProject/Bugs/3992/InstanceMethodDataSourceWithAsyncInitializerTests.cs index 733b3b6b72..3d817aa50d 100644 --- a/TUnit.TestProject/Bugs/3992/InstanceMethodDataSourceWithAsyncInitializerTests.cs +++ b/TUnit.TestProject/Bugs/3992/InstanceMethodDataSourceWithAsyncInitializerTests.cs @@ -121,7 +121,7 @@ await Assert.That(_testExecutionCount) // Verify that all tests used the SAME fixture instance (SharedType.PerClass) var uniqueInstanceIds = _observedInstanceIds.Distinct().ToList(); await Assert.That(uniqueInstanceIds) - .HasCount().EqualTo(1) + .Count().IsEqualTo(1) .Because("with SharedType.PerClass, all tests should share the same fixture instance"); // Reset for next run diff --git a/TUnit.TestProject/Bugs/4032/NestedAsyncInitializerTests.cs b/TUnit.TestProject/Bugs/4032/NestedAsyncInitializerTests.cs index 2497a2232d..b9d825c8b9 100644 --- a/TUnit.TestProject/Bugs/4032/NestedAsyncInitializerTests.cs +++ b/TUnit.TestProject/Bugs/4032/NestedAsyncInitializerTests.cs @@ -383,7 +383,7 @@ public async Task InitializationOrder_ShouldBeDeepestFirst() var order = DeepNestingInitializationTracker.GetOrder(); // Deep should be initialized first, then Middle, then Top - await Assert.That(order).HasCount().EqualTo(3) + await Assert.That(order).Count().IsEqualTo(3) .Because("there should be exactly 3 initializations"); await Assert.That(order[0]).IsEqualTo("Deep") diff --git a/TUnit.TestProject/Bugs/4584/DependenciesInAfterTestDiscoveryHookTests.cs b/TUnit.TestProject/Bugs/4584/DependenciesInAfterTestDiscoveryHookTests.cs index 7a20d64830..d90cf1343e 100644 --- a/TUnit.TestProject/Bugs/4584/DependenciesInAfterTestDiscoveryHookTests.cs +++ b/TUnit.TestProject/Bugs/4584/DependenciesInAfterTestDiscoveryHookTests.cs @@ -141,7 +141,7 @@ public async Task VerifyDependenciesWereCapturedInHook() // Verify the dependency was available in the hook var capturedDeps = DependenciesInAfterTestDiscoveryHookTests.CapturedDependenciesInHook[testId]; - await Assert.That(capturedDeps).HasCount().EqualTo(1); + await Assert.That(capturedDeps).Count().IsEqualTo(1); await Assert.That(capturedDeps[0].ClassType).IsEqualTo(typeof(DependencyTarget4584)); // Verify the dependency ran before us @@ -167,7 +167,7 @@ public async Task VerifyMethodDependenciesWereCapturedInHook() // Verify the dependency was available in the hook var capturedDeps = DependenciesInAfterTestDiscoveryHookTests.CapturedDependenciesInHook[testId]; - await Assert.That(capturedDeps).HasCount().EqualTo(1); + await Assert.That(capturedDeps).Count().IsEqualTo(1); } } @@ -229,7 +229,7 @@ public async Task VerifyTransitiveDependenciesWereCapturedInHook() // Verify BOTH direct and transitive dependencies were available in the hook var capturedDeps = DependenciesInAfterTestDiscoveryHookTests.CapturedDependenciesInHook[testId]; - await Assert.That(capturedDeps).HasCount().EqualTo(2); + await Assert.That(capturedDeps).Count().IsEqualTo(2); var depTypes = capturedDeps.Select(d => d.ClassType).ToList(); await Assert.That(depTypes).Contains(typeof(IntermediateDependency4584)); @@ -354,7 +354,7 @@ public async Task VerifyAllDependenciesVisible() var capturedDeps = DependenciesInAfterTestDiscoveryHookTests.CapturedDependenciesInHook[testId]; // Should see both middle and root - await Assert.That(capturedDeps).HasCount().EqualTo(2); + await Assert.That(capturedDeps).Count().IsEqualTo(2); var depTypes = capturedDeps.Select(d => d.ClassType).ToList(); await Assert.That(depTypes).Contains(typeof(MiddleDependency4584)); @@ -378,7 +378,7 @@ public async Task VerifyOnlyRootVisible() var capturedDeps = DependenciesInAfterTestDiscoveryHookTests.CapturedDependenciesInHook[testId]; // Should see only root - await Assert.That(capturedDeps).HasCount().EqualTo(1); + await Assert.That(capturedDeps).Count().IsEqualTo(1); await Assert.That(capturedDeps[0].ClassType).IsEqualTo(typeof(RootDependency4584)); } } diff --git a/TUnit.TestProject/Bugs/Issue2993/ImplicitConversionTests.cs b/TUnit.TestProject/Bugs/Issue2993/ImplicitConversionTests.cs index 79a43a14b7..18cacfcaa7 100644 --- a/TUnit.TestProject/Bugs/Issue2993/ImplicitConversionTests.cs +++ b/TUnit.TestProject/Bugs/Issue2993/ImplicitConversionTests.cs @@ -28,7 +28,7 @@ public async Task PrivateType_WithNullableIntImplicitOperator_NonEmptyCollection var items = new[] { item1, item2 }; await Assert.That(items).IsNotEmpty(); - await Assert.That(items).HasCount(2); + await Assert.That(items).Count().IsEqualTo(2); } // Test with non-nullable value type diff --git a/TUnit.TestProject/Bugs/NestedDisposalOrder/Tests.cs b/TUnit.TestProject/Bugs/NestedDisposalOrder/Tests.cs index 9ac02e0961..195092a44e 100644 --- a/TUnit.TestProject/Bugs/NestedDisposalOrder/Tests.cs +++ b/TUnit.TestProject/Bugs/NestedDisposalOrder/Tests.cs @@ -148,7 +148,7 @@ public static async Task VerifyDisposalOrder(TestSessionContext context) Console.WriteLine($"Dispose order: {string.Join(" -> ", disposeOrder)}"); // Init should be deepest first - await Assert.That(initOrder).HasCount().EqualTo(3); + await Assert.That(initOrder).Count().IsEqualTo(3); await Assert.That(initOrder[0]).IsEqualTo(nameof(ContextFactoryFixture2)) .Because("deepest dependency should be initialized first"); await Assert.That(initOrder[1]).IsEqualTo(nameof(AppSeedFixture2)) @@ -157,7 +157,7 @@ await Assert.That(initOrder[2]).IsEqualTo(nameof(AppServiceFixture2)) .Because("top-level dependency should be initialized last"); // Dispose should be reverse of init (shallowest first) - await Assert.That(disposeOrder).HasCount().EqualTo(3); + await Assert.That(disposeOrder).Count().IsEqualTo(3); await Assert.That(disposeOrder[0]).IsEqualTo(nameof(AppServiceFixture2)) .Because("top-level (shallowest) should be disposed first"); await Assert.That(disposeOrder[1]).IsEqualTo(nameof(AppSeedFixture2)) diff --git a/TUnit.TestProject/ClassHooks.cs b/TUnit.TestProject/ClassHooks.cs index 3d30c10cc6..f6424a5dcf 100644 --- a/TUnit.TestProject/ClassHooks.cs +++ b/TUnit.TestProject/ClassHooks.cs @@ -39,7 +39,7 @@ public static void AfterHook1() public static async Task AfterHook2(ClassHookContext context) { await Assert.That(context.TestCount).IsEqualTo(1); - await Assert.That(context.Tests.Where(x => x.Execution.Result?.State == TestState.Passed)).HasCount().EqualTo(1); + await Assert.That(context.Tests.Where(x => x.Execution.Result?.State == TestState.Passed)).Count().IsEqualTo(1); } [After(Class), Timeout(30_000)] @@ -52,7 +52,7 @@ public static void AfterHook3(CancellationToken cancellationToken) public static async Task AfterHook4(ClassHookContext context, CancellationToken cancellationToken) { await Assert.That(context.TestCount).IsEqualTo(1); - await Assert.That(context.Tests.Where(x => x.Execution.Result?.State == TestState.Passed)).HasCount().EqualTo(1); + await Assert.That(context.Tests.Where(x => x.Execution.Result?.State == TestState.Passed)).Count().IsEqualTo(1); } [Test] diff --git a/TUnit.TestProject/CombinedConstraintsSelfContainedTest.cs b/TUnit.TestProject/CombinedConstraintsSelfContainedTest.cs index 212dc8f4f3..aeb7a561a3 100644 --- a/TUnit.TestProject/CombinedConstraintsSelfContainedTest.cs +++ b/TUnit.TestProject/CombinedConstraintsSelfContainedTest.cs @@ -116,7 +116,7 @@ public async Task VerifyConstraintsCombineCorrectly() var log = CombinedConstraintTracker.ExecutionLog.OrderBy(x => x.Start).ToList(); // We should have 6 test executions - await Assert.That(log).HasCount().EqualTo(6); + await Assert.That(log).Count().IsEqualTo(6); // 1. Tests with same key should not overlap // Allow a small tolerance (50ms) for framework overhead and CI scheduling variability diff --git a/TUnit.TestProject/DependenciesAvailableInEventReceiverTests.cs b/TUnit.TestProject/DependenciesAvailableInEventReceiverTests.cs index cf9901698e..4b5d724cf7 100644 --- a/TUnit.TestProject/DependenciesAvailableInEventReceiverTests.cs +++ b/TUnit.TestProject/DependenciesAvailableInEventReceiverTests.cs @@ -65,7 +65,7 @@ public async Task DependentTest_HasDependenciesAtRegistration() // Verify the dependency was captured at registration time var capturedDeps = CaptureDependenciesAttribute.CapturedDependencies[testId]; - await Assert.That(capturedDeps).HasCount().EqualTo(1); + await Assert.That(capturedDeps).Count().IsEqualTo(1); await Assert.That(capturedDeps[0].TestName).IsEqualTo(nameof(IndependentTest)); } } @@ -103,7 +103,7 @@ public async Task Test_HasCrossClassDependenciesAtRegistration() // Verify the cross-class dependency was captured at registration time var capturedDeps = CaptureDependenciesAttribute.CapturedDependencies[testId]; - await Assert.That(capturedDeps).HasCount().EqualTo(1); + await Assert.That(capturedDeps).Count().IsEqualTo(1); await Assert.That(capturedDeps[0].ClassType).IsEqualTo(typeof(DependencyTargetClass)); await Assert.That(capturedDeps[0].TestName).IsEqualTo(nameof(DependencyTargetClass.TargetTest)); @@ -136,7 +136,7 @@ public async Task TestB_DependsOnC() var capturedDeps = CaptureDependenciesAttribute.CapturedDependencies[testId]; // B depends directly on C - await Assert.That(capturedDeps).HasCount().EqualTo(1); + await Assert.That(capturedDeps).Count().IsEqualTo(1); await Assert.That(capturedDeps[0].TestName).IsEqualTo(nameof(TestC_NoDependencies)); } @@ -148,7 +148,7 @@ public async Task TestA_DependsOnB_ShouldSeeTransitiveDependencies() var capturedDeps = CaptureDependenciesAttribute.CapturedDependencies[testId]; // A depends on B, but should also see C as a transitive dependency - await Assert.That(capturedDeps).HasCount().EqualTo(2); + await Assert.That(capturedDeps).Count().IsEqualTo(2); var depNames = capturedDeps.Select(d => d.TestName).ToList(); await Assert.That(depNames).Contains(nameof(TestB_DependsOnC)); diff --git a/TUnit.TestProject/DependencyCountTests.cs b/TUnit.TestProject/DependencyCountTests.cs index d2916b2f6f..b5e97aeeef 100644 --- a/TUnit.TestProject/DependencyCountTests.cs +++ b/TUnit.TestProject/DependencyCountTests.cs @@ -17,7 +17,7 @@ public Task Test1(int value) [Test, DependsOn(nameof(Test1))] public async Task Test2() { - await Assert.That(TestContext.Current!.Dependencies.DependsOn).HasCount().EqualTo(3); + await Assert.That(TestContext.Current!.Dependencies.DependsOn).Count().IsEqualTo(3); } [Test] @@ -29,7 +29,7 @@ public Task Test3() [Test, DependsOn(nameof(Test3))] public async Task Test4() { - await Assert.That(TestContext.Current!.Dependencies.DependsOn).HasCount().EqualTo(1); + await Assert.That(TestContext.Current!.Dependencies.DependsOn).Count().IsEqualTo(1); } [Test, DependsOn(nameof(Test1))] @@ -41,6 +41,6 @@ public Task Test5() [Test, DependsOn(nameof(Test5))] public async Task Test6() { - await Assert.That(TestContext.Current!.Dependencies.DependsOn).HasCount().EqualTo(4); + await Assert.That(TestContext.Current!.Dependencies.DependsOn).Count().IsEqualTo(4); } } diff --git a/TUnit.TestProject/DependencyFilteringTests.cs b/TUnit.TestProject/DependencyFilteringTests.cs index 098e164829..680504581f 100644 --- a/TUnit.TestProject/DependencyFilteringTests.cs +++ b/TUnit.TestProject/DependencyFilteringTests.cs @@ -36,7 +36,7 @@ public async Task DeepDependentTest() // Verify that TestContext.Dependencies is populated var context = TestContext.Current!; - await Assert.That(context.Dependencies.DependsOn).HasCount().EqualTo(1); + await Assert.That(context.Dependencies.DependsOn).Count().IsEqualTo(1); await Assert.That(context.Dependencies.DependsOn.ElementAt(0).TestName).IsEqualTo("DependentTest"); } @@ -49,7 +49,7 @@ public async Task IndependentTest() // Verify that TestContext.Dependencies is empty for independent tests var context = TestContext.Current!; - await Assert.That(context.Dependencies.DependsOn).HasCount().EqualTo(0); + await Assert.That(context.Dependencies.DependsOn).Count().IsEqualTo(0); } [Test] @@ -63,7 +63,7 @@ public async Task TestWithCrossClassDependency() // Verify that TestContext.Dependencies is populated with cross-class dependency var context = TestContext.Current!; - await Assert.That(context.Dependencies.DependsOn).HasCount().EqualTo(1); + await Assert.That(context.Dependencies.DependsOn).Count().IsEqualTo(1); await Assert.That(context.Dependencies.DependsOn.ElementAt(0).TestName).IsEqualTo("CrossClassDependency"); await Assert.That(context.Dependencies.DependsOn.ElementAt(0).ClassType.Name).IsEqualTo("DependencyFilteringTests2"); } diff --git a/TUnit.TestProject/DependsOnTests3.cs b/TUnit.TestProject/DependsOnTests3.cs index 247f322522..310430a067 100644 --- a/TUnit.TestProject/DependsOnTests3.cs +++ b/TUnit.TestProject/DependsOnTests3.cs @@ -42,8 +42,8 @@ public async Task Test3() var test1 = TestContext.Current!.Dependencies.GetTests(nameof(Test1)); var test2 = TestContext.Current.Dependencies.GetTests(nameof(Test2)); - await Assert.That(test1).HasCount().EqualTo(1); - await Assert.That(test2).HasCount().EqualTo(1); + await Assert.That(test1).Count().IsEqualTo(1); + await Assert.That(test2).Count().IsEqualTo(1); await Assert.That(test1[0].StateBag.Items).ContainsKey("Test1"); await Assert.That(test2[0].StateBag.Items).ContainsKey("Test2"); diff --git a/TUnit.TestProject/EventReceiverStageTests.cs b/TUnit.TestProject/EventReceiverStageTests.cs index 9b5439c7ff..444d4f75ac 100644 --- a/TUnit.TestProject/EventReceiverStageTests.cs +++ b/TUnit.TestProject/EventReceiverStageTests.cs @@ -161,7 +161,7 @@ public void TeardownTest() public async Task EarlyTestStartReceiver_RunsBeforeBeforeTestHook() { // Expected order: EarlyTestStart → BeforeTest → Test - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(2); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(2); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("EarlyTestStart"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("BeforeTest"); } @@ -171,7 +171,7 @@ public async Task EarlyTestStartReceiver_RunsBeforeBeforeTestHook() public async Task LateTestStartReceiver_RunsAfterBeforeTestHook() { // Expected order: BeforeTest → LateTestStart → Test - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(2); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(2); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("BeforeTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("LateTestStart"); } @@ -182,7 +182,7 @@ public async Task DefaultTestStartReceiver_RunsAfterBeforeTestHook_AsLateStage() { // Expected order: BeforeTest → DefaultTestStart → Test // Default should behave as Late stage - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(2); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(2); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("BeforeTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("DefaultTestStart"); } @@ -203,7 +203,7 @@ public async Task VerifyEarlyTestEndReceiverOrder(TestContext context) { // Expected order: BeforeTest → EarlyTestEnd → AfterTest await Task.Delay(10); // Small delay to ensure all receivers have executed - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(3); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(3); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("BeforeTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("EarlyTestEnd"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[2]).IsEqualTo("AfterTest"); @@ -225,7 +225,7 @@ public async Task VerifyLateTestEndReceiverOrder(TestContext context) { // Expected order: BeforeTest → AfterTest → LateTestEnd await Task.Delay(10); // Small delay to ensure all receivers have executed - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(3); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(3); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("BeforeTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("AfterTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[2]).IsEqualTo("LateTestEnd"); @@ -248,7 +248,7 @@ public async Task VerifyDefaultTestEndReceiverOrder(TestContext context) { // Expected order: BeforeTest → AfterTest → DefaultTestEnd await Task.Delay(10); // Small delay to ensure all receivers have executed - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(3); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(3); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("BeforeTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("AfterTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[2]).IsEqualTo("DefaultTestEnd"); @@ -262,7 +262,7 @@ public async Task EarlyStageReceivers_RespectOrderProperty() { // Expected order: EarlyTestStart_Order1 → EarlyTestStart_Order2 → BeforeTest → Test // Order property should still be respected within the same stage - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(3); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(3); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("EarlyTestStart_Order1"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("EarlyTestStart_Order2"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[2]).IsEqualTo("BeforeTest"); @@ -276,7 +276,7 @@ public async Task EarlyStageReceivers_RespectOrderProperty() public async Task MixedStageReceivers_ExecuteInCorrectOrder() { // Expected order: EarlyTestStart → BeforeTest → LateTestStart → Test → EarlyTestEnd → AfterTest → LateTestEnd - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(3); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(3); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("EarlyTestStart"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("BeforeTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[2]).IsEqualTo("LateTestStart"); @@ -289,7 +289,7 @@ public async Task VerifyMixedStageReceiversEndOrder(TestContext context) { // Expected final order: EarlyTestStart → BeforeTest → LateTestStart → EarlyTestEnd → AfterTest → LateTestEnd await Task.Delay(10); // Small delay to ensure all receivers have executed - await Assert.That(EventReceiverStageTracker.ExecutionOrder).HasCount().EqualTo(6); + await Assert.That(EventReceiverStageTracker.ExecutionOrder).Count().IsEqualTo(6); await Assert.That(EventReceiverStageTracker.ExecutionOrder[0]).IsEqualTo("EarlyTestStart"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[1]).IsEqualTo("BeforeTest"); await Assert.That(EventReceiverStageTracker.ExecutionOrder[2]).IsEqualTo("LateTestStart"); diff --git a/TUnit.TestProject/GlobalTestHooks.cs b/TUnit.TestProject/GlobalTestHooks.cs index 5f6cb4cca4..3a92224f3a 100644 --- a/TUnit.TestProject/GlobalTestHooks.cs +++ b/TUnit.TestProject/GlobalTestHooks.cs @@ -48,7 +48,7 @@ public class GlobalTestHooksTests [Test] public async Task SetUpTest1() { - await Assert.That(TestContext.Current?.StateBag.Items).HasCount().EqualTo(1); + await Assert.That(TestContext.Current?.StateBag.Items).Count().IsEqualTo(1); await Assert.That(TestContext.Current?.StateBag.Items.First().Key).IsEqualTo("SetUpCustomTestNameProperty"); await Assert.That(TestContext.Current?.StateBag.Items.First().Value).IsEquatableOrEqualTo("SetUpTest1"); } diff --git a/TUnit.TestProject/KeyedDataSourceTests.cs b/TUnit.TestProject/KeyedDataSourceTests.cs index d1528fa433..33f057dfaf 100644 --- a/TUnit.TestProject/KeyedDataSourceTests.cs +++ b/TUnit.TestProject/KeyedDataSourceTests.cs @@ -51,7 +51,7 @@ public async Task Key_IsAvailableDuringInitializeAsync(KeyAwareFixture fixture) [DependsOn(nameof(Key_IsAvailableDuringInitializeAsync))] public async Task SameKey_ReturnsSameInstance() { - await Assert.That(AlphaInstances).HasCount().EqualTo(2); + await Assert.That(AlphaInstances).Count().IsEqualTo(2); await Assert.That(AlphaInstances[0]).IsSameReferenceAs(AlphaInstances[1]); } } diff --git a/TUnit.TestProject/NestedTupleDataSourceTests.cs b/TUnit.TestProject/NestedTupleDataSourceTests.cs index fe508d3a11..1f8dc66a1b 100644 --- a/TUnit.TestProject/NestedTupleDataSourceTests.cs +++ b/TUnit.TestProject/NestedTupleDataSourceTests.cs @@ -63,7 +63,7 @@ public async Task MixedNestedTuple_SeparateParams(string value1, (int, bool) val [MethodDataSource(nameof(ArrayNestedTupleData))] public async Task ArrayNestedTuple_SeparateParams(int[] value1, (string, double) value2) { - await Assert.That(value1).HasCount(3); + await Assert.That(value1).Count().IsEqualTo(3); await Assert.That(value2.Item1).IsEqualTo("array"); await Assert.That(value2.Item2).IsEqualTo(3.14); } diff --git a/TUnit.TestProject/NotInParallelClassGroupingTests.cs b/TUnit.TestProject/NotInParallelClassGroupingTests.cs index 33891373bc..4cdc4bc86c 100644 --- a/TUnit.TestProject/NotInParallelClassGroupingTests.cs +++ b/TUnit.TestProject/NotInParallelClassGroupingTests.cs @@ -102,7 +102,7 @@ public async Task VerifyClassGrouping() } // We should have 8 test executions (3 from ClassA, 2 from ClassB, 3 from ClassC) - await Assert.That(order).HasCount(8); + await Assert.That(order).Count().IsEqualTo(8); // Verify that all tests from one class complete before another class starts var classSequence = new List(); @@ -128,9 +128,9 @@ public async Task VerifyClassGrouping() var classCTests = order.Where(o => o.StartsWith("ClassC.")).ToList(); // Check that we have the right number of tests from each class - await Assert.That(classATests).HasCount(3); - await Assert.That(classBTests).HasCount(2); - await Assert.That(classCTests).HasCount(3); + await Assert.That(classATests).Count().IsEqualTo(3); + await Assert.That(classBTests).Count().IsEqualTo(2); + await Assert.That(classCTests).Count().IsEqualTo(3); // Relaxed ordering check: Just verify all expected tests ran // In highly concurrent environments, even within-class ordering might vary diff --git a/TUnit.TestProject/TestContextIsolationTests.cs b/TUnit.TestProject/TestContextIsolationTests.cs index 116abad064..41085cb153 100644 --- a/TUnit.TestProject/TestContextIsolationTests.cs +++ b/TUnit.TestProject/TestContextIsolationTests.cs @@ -122,16 +122,16 @@ public async Task Verify_All_Contexts_Were_Unique() var allContexts = CapturedContexts.Values.Where(c => c != null).ToList(); // Verify we captured contexts - await Assert.That(allContexts).HasCount().GreaterThanOrEqualTo(15); // 3 tests * 5 repeats + await Assert.That(allContexts).Count().IsGreaterThanOrEqualTo(15); // 3 tests * 5 repeats // Verify all contexts are unique instances var uniqueContexts = allContexts.Distinct().ToList(); - await Assert.That(uniqueContexts).HasCount().EqualTo(allContexts.Count); + await Assert.That(uniqueContexts).Count().IsEqualTo(allContexts.Count); // Verify each test had its own TestLocalId var allTestIds = CapturedContexts.Keys.ToList(); var uniqueTestIds = allTestIds.Distinct().ToList(); - await Assert.That(uniqueTestIds).HasCount().EqualTo(allTestIds.Count); + await Assert.That(uniqueTestIds).Count().IsEqualTo(allTestIds.Count); } } diff --git a/TUnit.TestProject/Tests.cs b/TUnit.TestProject/Tests.cs index 2701bda62c..738b0c6014 100644 --- a/TUnit.TestProject/Tests.cs +++ b/TUnit.TestProject/Tests.cs @@ -64,7 +64,7 @@ public async Task Test4() [Category("Fail")] public async Task ParameterisedTests1(string value) { - await Assert.That(value).IsEqualTo("1").And.HasLength().EqualTo(1); + await Assert.That(value).IsEqualTo("1").And.Length().IsEqualTo(1); } [Test] @@ -242,14 +242,14 @@ public async Task Timeout1(CancellationToken cancellationToken) [Category("Pass")] public async Task String_And_Condition() { - await Assert.That("1").IsEqualTo("1").And.HasLength().EqualTo(1); + await Assert.That("1").IsEqualTo("1").And.Length().IsEqualTo(1); } [Test] [Category("Fail")] public async Task String_And_Condition2() { - await Assert.That("1").IsEqualTo("2").And.HasLength().EqualTo(2); + await Assert.That("1").IsEqualTo("2").And.Length().IsEqualTo(2); } [Test] @@ -257,7 +257,7 @@ public async Task String_And_Condition2() public async Task Count1() { var list = new List { 1, 2, 3 }; - await Assert.That(list).IsEquivalentTo([1, 2, 3]).And.HasCount().EqualTo(3); + await Assert.That(list).IsEquivalentTo([1, 2, 3]).And.Count().IsEqualTo(3); } [Test] @@ -290,7 +290,7 @@ public async Task Enumerable_NotEmpty() public async Task Count2() { var list = new List { 1, 2, 3 }; - await Assert.That(list).IsEquivalentTo([1, 2, 3, 4, 5]).And.HasCount().EqualTo(5); + await Assert.That(list).IsEquivalentTo([1, 2, 3, 4, 5]).And.Count().IsEqualTo(5); } [Test] @@ -301,7 +301,7 @@ public async Task AssertMultiple() using (Assert.Multiple()) { await Assert.That(list).IsEquivalentTo([1, 2, 3, 4, 5]); - await Assert.That(list).HasCount().EqualTo(5); + await Assert.That(list).Count().IsEqualTo(5); } } diff --git a/docs/docs/writing-tests/mocking/argument-matchers.md b/docs/docs/writing-tests/mocking/argument-matchers.md index 8af608f407..9579195027 100644 --- a/docs/docs/writing-tests/mocking/argument-matchers.md +++ b/docs/docs/writing-tests/mocking/argument-matchers.md @@ -217,7 +217,7 @@ svc.Greet("Charlie"); var all = nameArg.Values; // ["Alice", "Bob", "Charlie"] var last = nameArg.Latest; // "Charlie" -await Assert.That(nameArg.Values).HasCount().EqualTo(3); +await Assert.That(nameArg.Values).Count().IsEqualTo(3); ``` :::tip diff --git a/docs/docs/writing-tests/mocking/http.md b/docs/docs/writing-tests/mocking/http.md index 6e4f99fc96..d4f16f7b38 100644 --- a/docs/docs/writing-tests/mocking/http.md +++ b/docs/docs/writing-tests/mocking/http.md @@ -218,12 +218,12 @@ client.Handler.VerifyNoUnmatchedRequests(); ### Inspect Captured Requests ```csharp -await Assert.That(client.Handler.Requests).HasCount().EqualTo(2); +await Assert.That(client.Handler.Requests).Count().IsEqualTo(2); await Assert.That(client.Handler.Requests[0].Method).IsEqualTo(HttpMethod.Get); await Assert.That(client.Handler.Requests[0].RequestUri!.PathAndQuery).IsEqualTo("/api/users"); // Check for unmatched requests -await Assert.That(client.Handler.UnmatchedRequests).HasCount().EqualTo(0); +await Assert.That(client.Handler.UnmatchedRequests).Count().IsEqualTo(0); ``` Each `CapturedRequest` provides: diff --git a/docs/docs/writing-tests/mocking/logging.md b/docs/docs/writing-tests/mocking/logging.md index 02d4aaf411..bd203e99c9 100644 --- a/docs/docs/writing-tests/mocking/logging.md +++ b/docs/docs/writing-tests/mocking/logging.md @@ -57,7 +57,7 @@ logger.LogInformation("User {UserId} logged in", 42); logger.LogWarning("Disk space low"); // All entries -await Assert.That(logger.Entries).HasCount().EqualTo(2); +await Assert.That(logger.Entries).Count().IsEqualTo(2); await Assert.That(logger.Entries[0].LogLevel).IsEqualTo(LogLevel.Information); await Assert.That(logger.Entries[0].Message).Contains("42"); diff --git a/docs/docs/writing-tests/mocking/verification.md b/docs/docs/writing-tests/mocking/verification.md index fcad730960..6ffd665364 100644 --- a/docs/docs/writing-tests/mocking/verification.md +++ b/docs/docs/writing-tests/mocking/verification.md @@ -148,7 +148,7 @@ Access the raw call history for custom inspection: ```csharp var calls = mock.Invocations; -await Assert.That(calls).HasCount().EqualTo(3); +await Assert.That(calls).Count().IsEqualTo(3); await Assert.That(calls[0].MemberName).IsEqualTo("GetUser"); ``` diff --git a/docs/src/components/AssertionsLibrary/index.tsx b/docs/src/components/AssertionsLibrary/index.tsx index 1111e4474b..5110499953 100644 --- a/docs/src/components/AssertionsLibrary/index.tsx +++ b/docs/src/components/AssertionsLibrary/index.tsx @@ -35,12 +35,12 @@ const assertionsData: Assertion[] = [ { name: 'EndsWith', category: 'String', description: 'Asserts the string ends with the expected suffix', syntax: 'await Assert.That(actual).EndsWith(suffix)', example: 'await Assert.That("hello world").EndsWith("world")' }, { name: 'IsEmpty', category: 'String', description: 'Asserts the string is empty', syntax: 'await Assert.That(actual).IsEmpty()', example: 'await Assert.That("").IsEmpty()' }, { name: 'IsNotEmpty', category: 'String', description: 'Asserts the string is not empty', syntax: 'await Assert.That(actual).IsNotEmpty()', example: 'await Assert.That("text").IsNotEmpty()' }, - { name: 'HasLength', category: 'String', description: 'Asserts the string has the expected length', syntax: 'await Assert.That(actual).HasLength().EqualTo(length)', example: 'await Assert.That("hello").HasLength().EqualTo(5)' }, + { name: 'Length', category: 'String', description: 'Asserts the string has the expected length', syntax: 'await Assert.That(actual).Length().IsEqualTo(length)', example: 'await Assert.That("hello").Length().IsEqualTo(5)' }, // Collections { name: 'Contains (Collection)', category: 'Collections', description: 'Asserts the collection contains the expected item', syntax: 'await Assert.That(collection).Contains(item)', example: 'await Assert.That(list).Contains(5)' }, { name: 'DoesNotContain (Collection)', category: 'Collections', description: 'Asserts the collection does not contain the item', syntax: 'await Assert.That(collection).DoesNotContain(item)', example: 'await Assert.That(list).DoesNotContain(10)' }, - { name: 'HasCount', category: 'Collections', description: 'Asserts the collection has the expected count', syntax: 'await Assert.That(collection).HasCount().EqualTo(count)', example: 'await Assert.That(list).HasCount().EqualTo(3)' }, + { name: 'Count', category: 'Collections', description: 'Asserts the collection has the expected count', syntax: 'await Assert.That(collection).Count().IsEqualTo(count)', example: 'await Assert.That(list).Count().IsEqualTo(3)' }, { name: 'IsEmpty (Collection)', category: 'Collections', description: 'Asserts the collection is empty', syntax: 'await Assert.That(collection).IsEmpty()', example: 'await Assert.That(emptyList).IsEmpty()' }, { name: 'IsNotEmpty (Collection)', category: 'Collections', description: 'Asserts the collection is not empty', syntax: 'await Assert.That(collection).IsNotEmpty()', example: 'await Assert.That(list).IsNotEmpty()' }, { name: 'IsEquivalentTo', category: 'Collections', description: 'Asserts collections have equivalent items (order-independent)', syntax: 'await Assert.That(collection).IsEquivalentTo(expected)', example: 'await Assert.That(list).IsEquivalentTo([1,2,3])' }, diff --git a/docs/src/components/HomepageFeatures/index.tsx b/docs/src/components/HomepageFeatures/index.tsx index b5af84e948..a7923c3162 100644 --- a/docs/src/components/HomepageFeatures/index.tsx +++ b/docs/src/components/HomepageFeatures/index.tsx @@ -41,7 +41,7 @@ public async Task TestAsync() var result = await GetDataAsync(); await Assert.That(result) .IsNotNull() - .And.HasCount(5); + .And.Count().IsEqualTo(5); }` }, {