Skip to content

fix: Contains for collections with duplicates in expected#642

Merged
vbreuss merged 2 commits intomainfrom
topic/fix-collection-contains-with-duplicate-in-expected
Jun 20, 2025
Merged

fix: Contains for collections with duplicates in expected#642
vbreuss merged 2 commits intomainfrom
topic/fix-collection-contains-with-duplicate-in-expected

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented Jun 20, 2025

Fixes the behavior of the Contains assertion when the expected collection includes duplicates yet some expected items are missing.

Ensure that the following test succeeds:

[Fact]
public async Task WhenExpectedContainsDuplicateButMissingItems_ShouldFail()
{
	int[] collection = [1, 2, 1, 3, 12, 2, 2,];

	async Task Act()
		=> await That(collection).Contains([1, 2, 1, 1, 2,]);

	await That(Act).Throws<XunitException>()
		.WithMessage("""
		             Expected that collection
		             contains collection [1, 2, 1, 1, 2,] in order,
		             but it
		               contained item 3 at index 3 instead of 1 and
		               contained item 12 at index 4 instead of 2

		             Collection:
		             [1, 2, 1, 3, 12, 2, 2]

		             Expected:
		             [1, 2, 1, 1, 2]
		             """);
}

Ensure that the following test succeeds:
```csharp
[Fact]
public async Task WhenExpectedContainsDuplicateButMissingItems_ShouldFail()
{
	int[] collection = [1, 2, 1, 3, 12, 2, 2,];

	async Task Act()
		=> await That(collection).Contains([1, 2, 1, 1, 2,]);

	await That(Act).Throws<XunitException>()
		.WithMessage("""
		             Expected that collection
		             contains collection [1, 2, 1, 1, 2,] in order,
		             but it
		               contained item 3 at index 3 instead of 1 and
		               contained item 12 at index 4 instead of 2

		             Collection:
		             [1, 2, 1, 3, 12, 2, 2]

		             Expected:
		             [1, 2, 1, 1, 2]
		             """);
}
```
@vbreuss vbreuss self-assigned this Jun 20, 2025
Copilot AI review requested due to automatic review settings June 20, 2025 10:07
@vbreuss vbreuss added the bug Something isn't working label Jun 20, 2025
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes the behavior of the Contains assertion when the expected collection includes duplicates yet some expected items are missing. The changes improve the error messages by including detailed information about mismatches and adjust the underlying options for duplicate handling.

  • Added a new test to verify failure when duplicates in the expected collection are partially missing.
  • Updated multiple test files to refine error message output with precise mismatch information.
  • Modified the CollectionMatchOptions to remove a conditional check that filtered out duplicate discrepancies.

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.CollectionTests.cs Added a new test and updated error message formatting for duplicate checks.
Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.CollectionImmutableTests.cs Updated error messages to include item mismatch details.
Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.CollectionEnumerableTests.cs Updated error messages to include item mismatch details.
Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.Contains.CollectionTests.cs Updated error messages to include item mismatch details.
Source/aweXpect.Core/Options/CollectionMatchOptions.cs Removed a duplicate filtering condition to improve error reporting on mismatches.
Comments suppressed due to low confidence (1)

Source/aweXpect.Core/Options/CollectionMatchOptions.cs:166

  • Removing the duplicate check now causes all mismatches to be reported, including for collections without duplicates. Verify that this behavior is aligned with the desired user experience, and consider adding tests for non-duplicate scenarios to confirm the change.
			}

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 20, 2025

Test Results

    4 files   -     34      4 suites   - 34   20s ⏱️ - 2m 23s
  888 tests  - 12 729    887 ✅  - 12 728  1 💤  - 1  0 ❌ ±0 
2 550 runs   - 35 343  2 549 ✅  - 35 342  1 💤  - 1  0 ❌ ±0 

Results for commit 9c8d809. ± Comparison against base commit 56b575b.

This pull request removes 12783 and adds 54 tests. Note that renamed tests count towards both.
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenAwaited_ShouldNotBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenAwaited_WithoutReturnValue_ShouldNotBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenNotAwaited_ShouldBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenNotAwaited_WithoutReturnValue_ShouldBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenNotAwaited_WithoutReturnValue_WithVerifyInMethod_ShouldStillBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenVerifiedStatically_ShouldNotBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenVerifiedStatically_WithoutReturnValue_ShouldNotBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenVerifiedWithStaticUsing_ShouldNotBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenVerifiedWithStaticUsing_WithoutReturnValue_ShouldNotBeFlagged
aweXpect.Analyzers.Tests.AwaitExpectationAnalyzerTests ‑ WhenVerified_ShouldNotBeFlagged
…
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message0d35c906-b620-45a7-99aa-4337c1b2c011")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message7051c7ac-c5f1-41c5-a716-db7604d8b511")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "messagea7d37f76-bc13-453a-8078-38ca577f024f")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message5526a667-6ae0-435b-b9c3-926f5fc36bef")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message86acf4d4-9db0-49c2-b651-1fe81b0bb4c1")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message9d9cd52f-ba96-423b-b6cc-8e6967c5781b")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnoreafde8641-34e6-410c-8ab0-b3b9cc38dfc5")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnorec285075e-a871-4a03-b40c-e3f76c474ab4")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnoref16d0c01-2301-4db9-bdc0-a424fcc2607d")
aweXpect.Core.Tests.FailTests ‑ Test_ShouldThrowException(reason: "reason2800e021-5146-41ca-a8f6-fe962225aace")
…

♻️ This comment has been updated with latest results.

@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown
Contributor

🚀 Benchmark Results

Details

BenchmarkDotNet v0.14.0, Ubuntu 24.04.2 LTS (Noble Numbat)
AMD EPYC 7763, 1 CPU, 4 logical and 2 physical cores
.NET SDK 8.0.411
[Host] : .NET 8.0.17 (8.0.1725.26602), X64 RyuJIT AVX2

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Method Mean Error StdDev Gen0 Gen1 Allocated
Bool_aweXpect 198.7 ns 2.32 ns 2.17 ns 0.0281 - 472 B
Bool_FluentAssertions 244.6 ns 5.00 ns 4.68 ns 0.0567 - 952 B
Bool_TUnit 943.0 ns 12.44 ns 11.64 ns 0.1440 - 2416 B
Equivalency_aweXpect 279,625.9 ns 1,375.49 ns 1,219.34 ns 16.6016 0.4883 284940 B
Equivalency_FluentAssertions 2,283,513.9 ns 14,399.77 ns 13,469.56 ns 273.4375 46.8750 4584416 B
Equivalency_TUnit 678,182.9 ns 2,336.66 ns 1,951.21 ns 51.7578 2.9297 866777 B
Int_GreaterThan_aweXpect 221.8 ns 5.21 ns 4.87 ns 0.0467 - 784 B
Int_GreaterThan_FluentAssertions 245.5 ns 6.21 ns 5.80 ns 0.0730 - 1224 B
Int_GreaterThan_TUnit 1,255.7 ns 18.44 ns 17.25 ns 0.1774 - 2992 B
ItemsCount_AtLeast_aweXpect 478.3 ns 4.82 ns 4.28 ns 0.0854 - 1432 B
ItemsCount_AtLeast_FluentAssertions 510.9 ns 3.11 ns 2.76 ns 0.1192 - 2008 B
ItemsCount_AtLeast_TUnit 14,399.1 ns 136.90 ns 121.36 ns 1.6327 - 27488 B
String_aweXpect 349.2 ns 2.59 ns 2.30 ns 0.0672 - 1128 B
String_FluentAssertions 479.6 ns 8.19 ns 7.66 ns 0.1287 - 2168 B
String_TUnit 1,344.4 ns 8.94 ns 7.47 ns 0.1850 - 3096 B
StringArray_aweXpect 1,459.4 ns 28.01 ns 26.20 ns 0.1640 - 2752 B
StringArray_FluentAssertions 1,294.0 ns 16.23 ns 15.19 ns 0.2480 - 4152 B
StringArray_TUnit 2,833.6 ns 26.48 ns 24.77 ns 0.2708 - 4576 B
StringArrayInAnyOrder_aweXpect 1,670.7 ns 16.71 ns 15.63 ns 0.1736 - 2912 B
StringArrayInAnyOrder_FluentAssertions 154,270.7 ns 543.83 ns 508.69 ns 3.4180 - 63787 B
StringArrayInAnyOrder_TUnit 4,787.2 ns 28.29 ns 25.08 ns 0.3967 - 6744 B

@github-actions
Copy link
Copy Markdown
Contributor

👽 Mutation Results

Mutation testing badge

aweXpect

Details
File Score Killed Survived Timeout No Coverage Ignored Compile Errors Total Detected Total Undetected Total Mutants

The final mutation score is NaN%

Coverage Thresholds: high:80 low:60 break:0

aweXpect.Core

Details
File Score Killed Survived Timeout No Coverage Ignored Compile Errors Total Detected Total Undetected Total Mutants
Options/CollectionMatchOptions.cs 100.00% 48 0 0 0 14 47 48 0 109

The final mutation score is 100.00%

Coverage Thresholds: high:80 low:60 break:0

@vbreuss vbreuss enabled auto-merge (squash) June 20, 2025 10:21
@vbreuss vbreuss merged commit f281ddd into main Jun 20, 2025
13 checks passed
@vbreuss vbreuss deleted the topic/fix-collection-contains-with-duplicate-in-expected branch June 20, 2025 10:22
@github-actions
Copy link
Copy Markdown
Contributor

This is addressed in release v2.17.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working state: released The issue is released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants