Skip to content

fix: avoid duplicate contexts in collection expectations#641

Merged
vbreuss merged 1 commit intomainfrom
topic/avoid-duplicate-collection-contexts
Jun 19, 2025
Merged

fix: avoid duplicate contexts in collection expectations#641
vbreuss merged 1 commit intomainfrom
topic/avoid-duplicate-collection-contexts

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented Jun 19, 2025

When combining multiple collection expectations with multiple failures, the context contained one collection context for every failure.

When combining multiple collection expectations with multiple failures, the context contained one collection context for every failure.
@vbreuss vbreuss self-assigned this Jun 19, 2025
Copilot AI review requested due to automatic review settings June 19, 2025 16:23
@vbreuss vbreuss added the bug Something isn't working label Jun 19, 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 ensures that when multiple collection expectations fail in a single assertion chain, the collection context is only included once. It adds tests across various collection types to verify the behavior and updates the context-addition logic to prevent duplicate contexts.

  • Added WithMultipleFailures_ShouldIncludeCollectionOnlyOnce tests for ReadOnlyDictionary, Dictionary, Enumerable, ImmutableArray, and AsyncEnumerable scenarios.
  • Modified CollectionHelpers to only add a "Collection" or "Dictionary" context if it hasn't been added already.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
Tests/...ThatReadOnlyDictionary.ContainsKey.Tests.cs Added multi-failure test for IReadOnlyDictionary.ContainsKey
Tests/...ThatDictionary.ContainsKey.Tests.cs Added multi-failure test for IDictionary.ContainsKey
Tests/...ThatEnumerable.Contains.Tests.cs Added multi-failure test for IEnumerable.Contains
Tests/...Contains.ImmutableTests.cs Added multi-failure test for ImmutableArray.Contains
Tests/...Contains.EnumerableTests.cs Added multi-failure test for non-generic IEnumerable.Contains
Tests/...ThatAsyncEnumerable.Contains.Tests.cs Added multi-failure test for IAsyncEnumerable.Contains
Source/aweXpect/.../CollectionHelpers.cs Wrapped context updates in conditional blocks to avoid duplicates
Comments suppressed due to low confidence (6)

Source/aweXpect/That/Collections/CollectionHelpers.cs:41

  • [nitpick] The conditional context-addition logic is duplicated across multiple overloads. Consider extracting a shared helper method to reduce repetition and improve maintainability.
	internal static ExpectationBuilder AddCollectionContext<TItem>(this ExpectationBuilder expectationBuilder,

Source/aweXpect/That/Collections/CollectionHelpers.cs:64

  • The lambda passed to UpdateContexts uses a block but never returns the modified contexts list, leading to a compile error or unexpected behavior. Add return contexts; before the closing brace.
		});

Source/aweXpect/That/Collections/CollectionHelpers.cs:100

  • The lambda block in AddCollectionContext(this ExpectationBuilder, object) does not return the updated contexts. You need to return contexts; at the end of the block.
		});

Source/aweXpect/That/Collections/CollectionHelpers.cs:124

  • Missing return contexts; in the UpdateContexts block for the .NET 8+ overload. Without it, the updated contexts won't be passed back.
		});

Source/aweXpect/That/Collections/CollectionHelpers.cs:147

  • In the generic dictionary overload, the UpdateContexts lambda block fails to return the modified contexts. Please add return contexts;.
		});

Source/aweXpect/That/Collections/CollectionHelpers.cs:169

  • The UpdateContexts block in the second IDictionary overload doesn't return contexts. Insert return contexts; to fix functionality.
		});

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 19, 2025

@github-actions
Copy link
Copy Markdown
Contributor

Test Results

    14 files   - 24      14 suites   - 24   2m 43s ⏱️ -33s
13 589 tests  - 23  13 587 ✅  - 23  2 💤 ±0  0 ❌ ±0 
37 821 runs   - 54  37 819 ✅  - 54  2 💤 ±0  0 ❌ ±0 

Results for commit 213ec22. ± Comparison against base commit d832baa.

This pull request removes 1379 and adds 1356 tests. Note that renamed tests count towards both.
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message02928d9c-f28d-423d-ba36-28b8490fe4e9")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "messagef5bdf959-f831-4a0a-85e0-468d3dc3763e")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "messagefa7b17b7-fe47-4f99-b2c8-50ef5d2b9294")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message16dfb73f-ede9-4cb9-88de-691f069eec98")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message4169ce2d-307a-4023-959e-a8d646c6ce4a")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message7976e511-7962-40e7-867c-eb9c2ceab0e7")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnore4f7e2406-528d-449e-ba70-0ba3ed9bc330")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnoreca13c48c-6cc9-4e2f-bd79-b8544ea1064b")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnoreee740483-92a0-48b6-bdd2-d8054e14c7f8")
aweXpect.Core.Tests.FailTests ‑ Test_ShouldThrowException(reason: "reason4ae943aa-fd66-4526-986e-a895e1fdca49")
…
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message3b821ef4-1c7f-4b87-b6a2-9bcebd46d430")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message84e9e679-7192-4c37-8c77-cd7a7168345b")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "messagef2e82269-4d6f-4216-880f-22f56ccc8c5e")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message29f04989-c5f5-4505-8c8c-54e37e28c612")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message47c0065d-98f0-4ff6-b593-84fff5776a74")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "messagebd60747d-bb62-46be-9ee5-669fcfdd4c15")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnore876eebb8-215c-4453-b1f0-f2aeebe52c45")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnoreaba1978b-1bdf-4f9d-a56b-9cb08cfd544a")
aweXpect.Core.Tests.Equivalency.EquivalencyOptionsExtensionsTests ‑ Generic_For_IgnoringMember_ShouldSetOptionForType(memberToIgnore: "memberToIgnorefb849922-cf77-42ef-a4aa-929d9d8238fb")
aweXpect.Core.Tests.FailTests ‑ Test_ShouldThrowException(reason: "reason5e1df0c6-c286-42b2-8558-2f4076e75d92")
…

@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 176.5 ns 1.08 ns 0.96 ns 0.0281 - 472 B
Bool_FluentAssertions 279.5 ns 0.83 ns 0.73 ns 0.0567 - 952 B
Bool_TUnit 916.7 ns 2.47 ns 2.06 ns 0.1440 - 2416 B
Equivalency_aweXpect 281,593.6 ns 1,441.54 ns 1,277.89 ns 16.6016 0.4883 284940 B
Equivalency_FluentAssertions 2,189,502.1 ns 7,784.35 ns 7,281.49 ns 273.4375 46.8750 4584416 B
Equivalency_TUnit 649,312.1 ns 2,328.72 ns 2,178.29 ns 51.7578 2.9297 866777 B
Int_GreaterThan_aweXpect 208.6 ns 0.68 ns 0.60 ns 0.0467 - 784 B
Int_GreaterThan_FluentAssertions 279.3 ns 0.53 ns 0.47 ns 0.0730 - 1224 B
Int_GreaterThan_TUnit 1,213.6 ns 9.07 ns 8.49 ns 0.1774 - 2992 B
ItemsCount_AtLeast_aweXpect 442.8 ns 3.10 ns 2.90 ns 0.0854 - 1432 B
ItemsCount_AtLeast_FluentAssertions 471.3 ns 4.39 ns 4.11 ns 0.1197 - 2008 B
ItemsCount_AtLeast_TUnit 14,526.3 ns 66.60 ns 62.30 ns 1.6327 - 27488 B
String_aweXpect 322.7 ns 0.75 ns 0.59 ns 0.0672 - 1128 B
String_FluentAssertions 500.1 ns 2.34 ns 2.19 ns 0.1287 - 2168 B
String_TUnit 1,273.1 ns 4.26 ns 3.77 ns 0.1850 - 3096 B
StringArray_aweXpect 1,354.9 ns 5.19 ns 4.86 ns 0.1640 - 2752 B
StringArray_FluentAssertions 1,255.4 ns 6.64 ns 5.88 ns 0.2480 - 4152 B
StringArray_TUnit 2,776.2 ns 7.72 ns 7.22 ns 0.2708 - 4576 B
StringArrayInAnyOrder_aweXpect 1,518.9 ns 2.93 ns 2.60 ns 0.1736 - 2912 B
StringArrayInAnyOrder_FluentAssertions 151,004.5 ns 541.47 ns 506.49 ns 3.4180 - 63787 B
StringArrayInAnyOrder_TUnit 4,610.1 ns 13.90 ns 13.00 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
That/Collections/CollectionHelpers.cs 89.89% 80 6 0 3 23 29 80 9 141

The final mutation score is 89.89%

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

The final mutation score is NaN%

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

@vbreuss vbreuss merged commit 56b575b into main Jun 19, 2025
13 checks passed
@vbreuss vbreuss deleted the topic/avoid-duplicate-collection-contexts branch June 19, 2025 17:55
github-actions Bot added a commit that referenced this pull request Jun 19, 2025
github-actions Bot added a commit that referenced this pull request Jun 19, 2025
@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