Skip to content

feat: support async Because reason#880

Merged
vbreuss merged 1 commit intomainfrom
topic/async-because
Jan 18, 2026
Merged

feat: support async Because reason#880
vbreuss merged 1 commit intomainfrom
topic/async-because

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented Jan 18, 2026

This PR adds support for asynchronous Because reasons in the aweXpect assertion library, allowing users to provide a Task<string> as the reason for an expectation.

Key Changes:

  • Introduces IBecauseReason interface to support both synchronous and asynchronous reason handling
  • Adds AsyncBecauseReason struct to handle Task<string> reasons
  • Updates ExpectationResult to accept Task<string> in Because() method

@vbreuss vbreuss self-assigned this Jan 18, 2026
@vbreuss vbreuss added the enhancement New feature or request label Jan 18, 2026
Copilot AI review requested due to automatic review settings January 18, 2026 15:07
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 adds support for asynchronous Because reasons in the aweXpect assertion library, allowing users to provide a Task<string> as the reason for an expectation.

Changes:

  • Introduces IBecauseReason interface to support both synchronous and asynchronous reason handling
  • Adds AsyncBecauseReason struct to handle Task<string> reasons
  • Updates ExpectationResult to accept Task<string> in Because() method

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Source/aweXpect.Core/Core/Helpers/IBecauseReason.cs New interface defining async contract for applying reasons to constraint results
Source/aweXpect.Core/Core/Helpers/BecauseReason.cs Updated to implement IBecauseReason interface with async return type
Source/aweXpect.Core/Core/Helpers/AsyncBecauseReason.cs New struct implementing async reason handling for Task<string>
Source/aweXpect.Core/Core/ExpectationBuilder.cs Adds overload to support Task<string> reasons
Source/aweXpect.Core/Results/ExpectationResult.cs Adds Because(Task<string>) overloads for async reason support
Source/aweXpect.Core/Core/Nodes/Node.cs Updates abstract method signature to use IBecauseReason
Source/aweXpect.Core/Core/Nodes/ExpectationNode.cs Refactors to apply reason asynchronously after constraint evaluation
Source/aweXpect.Core/Core/Nodes/AndNode.cs Updates to use IBecauseReason interface
Source/aweXpect.Core/Core/Nodes/OrNode.cs Updates to use IBecauseReason interface
Source/aweXpect.Core/Core/Nodes/WhichNode.cs Updates to use IBecauseReason interface
Tests/aweXpect.Core.Tests/Core/BecauseTests.cs Adds test coverage for async Because functionality with Action and Func delegates
Tests/aweXpect.Core.Tests/TestHelpers/DummyNode.cs Updates test helper to use IBecauseReason interface
Tests/aweXpect.Core.Api.Tests/ApiAcceptance.cs Removes [Explicit] attribute to enable API acceptance test


internal interface IBecauseReason
{

Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

Remove unnecessary blank line inside the interface definition.

Suggested change

Copilot uses AI. Check for mistakes.
/// </summary>
[TestCase]
[Explicit]
public async Task AcceptApiChanges()
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The removal of the [Explicit] attribute enables this test to run automatically. This test updates the expected public API to match the current API surface, which should typically require manual intervention. Ensure this change is intentional and that the API changes in this PR have been reviewed and approved before allowing automatic execution of this test.

Copilot uses AI. Check for mistakes.
@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown
Contributor

Test Results

     23 files   - 27       23 suites   - 27   7m 8s ⏱️ - 1m 37s
 19 517 tests  - 27   19 516 ✅  - 26  1 💤  - 1  0 ❌ ±0 
101 000 runs   - 63  100 999 ✅  - 62  1 💤  - 1  0 ❌ ±0 

Results for commit f3f91af. ± Comparison against base commit 9f92c67.

This pull request removes 3108 and adds 3081 tests. Note that renamed tests count towards both.
aweXpect.Core.Tests.Core.BecauseTests ‑ Delegate_ShouldApplyBecauseReason
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message20cc43aa-2219-49ff-985e-9d7595049dff")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message2b6658e6-358e-4410-b52b-748c522d78ad")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message45c0374c-ab57-4936-a68e-f3981ceb6f1e")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message646cbbcb-e3bb-4ce1-b0ba-3266b3390b9d")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message788c38be-8beb-4e04-a473-15ce11c642f0")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message8c3d46d1-dfe5-419c-b8d0-664ffac9b62b")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message3b60baff-0457-4ac3-9465-10b71c079416")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message74812392-9c68-4bcc-9714-d1923c48602d")
aweXpect.Core.Tests.Core.Exceptions.SkipExceptionTests ‑ Message_ShouldBeSet(message: "message885e1ccc-dde1-4e50-b5eb-0294922a3837")
…
aweXpect.Core.Tests.Core.BecauseTests ‑ ActionDelegate_ShouldApplyAsyncBecauseReason
aweXpect.Core.Tests.Core.BecauseTests ‑ ActionDelegate_ShouldApplyBecauseReason
aweXpect.Core.Tests.Core.BecauseTests ‑ FuncDelegate_ShouldApplyAsyncBecauseReason
aweXpect.Core.Tests.Core.BecauseTests ‑ FuncDelegate_ShouldApplyBecauseReason
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message19fc54ab-1635-4940-9217-39108a40e640")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message3ce11f0f-57b9-46d8-91e9-cc74ae5e17d0")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message3f6c0126-18da-463a-85a8-49a7746e6266")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message4288edf7-86b0-4a5b-afe3-2500f37202d0")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "message9ddb7627-7d12-417d-87fa-760d129f3fa1")
aweXpect.Core.Tests.Core.Exceptions.FailExceptionTests ‑ Message_ShouldBeSet(message: "messageb93c025c-9c43-46d1-a55c-b3514d94d5cf")
…

@github-actions
Copy link
Copy Markdown
Contributor

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.3 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.102
[Host] : .NET 8.0.23 (8.0.23, 8.0.2325.60607), X64 RyuJIT x86-64-v3

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

Method Mean Error StdDev Gen0 Gen1 Allocated
Bool_aweXpect 266.1 ns 5.14 ns 4.29 ns 0.0424 - 712 B
Bool_FluentAssertions 253.4 ns 5.81 ns 5.15 ns 0.0567 - 952 B
Equivalency_aweXpect 300,783.6 ns 3,260.17 ns 3,049.57 ns 20.0195 0.4883 335452 B
Equivalency_FluentAssertions 2,729,955.1 ns 44,951.63 ns 42,047.78 ns 285.1563 46.8750 4804906 B
Int_GreaterThan_aweXpect 270.8 ns 3.83 ns 3.59 ns 0.0486 - 816 B
Int_GreaterThan_FluentAssertions 271.3 ns 4.50 ns 4.21 ns 0.0730 - 1224 B
ItemsCount_AtLeast_aweXpect 518.4 ns 3.15 ns 2.79 ns 0.0811 - 1368 B
ItemsCount_AtLeast_FluentAssertions 511.8 ns 9.32 ns 8.72 ns 0.1192 - 2008 B
String_aweXpect 503.3 ns 3.40 ns 3.01 ns 0.0677 - 1136 B
String_FluentAssertions 1,319.3 ns 12.25 ns 11.45 ns 0.2346 - 3944 B
StringArray_aweXpect 1,943.0 ns 27.65 ns 25.87 ns 0.1564 - 2632 B
StringArray_FluentAssertions 1,338.6 ns 18.67 ns 16.55 ns 0.2480 - 4152 B
StringArrayInAnyOrder_aweXpect 2,593.1 ns 5.42 ns 5.07 ns 0.1678 - 2824 B
StringArrayInAnyOrder_FluentAssertions 87,771.6 ns 432.16 ns 383.10 ns 3.4180 - 58598 B

@vbreuss vbreuss merged commit 23cb7fa into main Jan 18, 2026
14 checks passed
@vbreuss vbreuss deleted the topic/async-because branch January 18, 2026 15:29
github-actions Bot added a commit that referenced this pull request Jan 18, 2026
github-actions Bot added a commit that referenced this pull request Jan 18, 2026
@github-actions
Copy link
Copy Markdown
Contributor

This is addressed in release v2.30.0.

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

Labels

enhancement New feature or request state: released The issue is released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants