Skip to content

Add floating-point assertions, numeric comparison assertions, Contain for enumerables, and async action assertions#195

Open
Copilot wants to merge 3 commits intomainfrom
copilot/add-floating-point-assertions
Open

Add floating-point assertions, numeric comparison assertions, Contain for enumerables, and async action assertions#195
Copilot wants to merge 3 commits intomainfrom
copilot/add-floating-point-assertions

Conversation

Copy link
Contributor

Copilot AI commented Feb 19, 2026

Adds four missing assertion capabilities needed for projects working with numeric comparisons, enumerable containment, and async code.

New: FloatingPointAssertions<T> (IFloatingPoint<T> constrained)

float and double now get a dedicated assertions type via Should():

result.Reward.Should().BeApproximately(17.5, 0.1);
result.Reward.Should().BeGreaterThanOrEqualTo(0.0);
fileInfo.Length.Should().BeGreaterThan(0L); // also on IntegerAssertions
  • BeApproximately(T expected, T precision) — asserts |value − expected| ≤ precision
  • BeLessThan, BeLessThanOrEqualTo, BeGreaterThan, BeGreaterThanOrEqualTo
  • FloatingPointAssertionsChain<T> for .And chaining

Numeric comparisons on IntegerAssertions<T>

BeLessThan, BeLessThanOrEqualTo, BeGreaterThan, BeGreaterThanOrEqualTo added — leverages the existing IBinaryInteger<T> constraint's IComparisonOperators.

Contain on EnumerableAssertions<TEnumerable, T>

results.Should().Contain(expectedItem);

Asserts the enumerable contains a specific item; throws "Value should contain {expected} but did not." on failure.

New: AsyncActionAssertions for Func<Task>

Async delegates now have a dedicated assertions type via Should(), mirroring the existing ActionAssertions API:

await multiEnvironment.Awaiting(m => m.StopAsync()).Should().ThrowAsync<SomeException>("expected message");
await service.Awaiting(s => s.StartAsync()).Should().NotThrowAsync();
  • ThrowAsync<TException>() — asserts the async action throws the specified exception type, returns Task<ActionAssertionsChain<TException>>
  • ThrowAsync<TException>(string expectedMessage) — with message check
  • NotThrowAsync() — asserts the async action does not throw

InvokingExtensions gains Awaiting<T>(this T value, Func<T, Task> action) and Awaiting<T, TResult>(this T value, Func<T, Task<TResult>> action) for wrapping async methods on a value for assertion testing.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…sertions, and Contain for EnumerableAssertions

Co-authored-by: MrKWatkins <345796+MrKWatkins@users.noreply.github.com>
Copilot AI changed the title [WIP] Add floating point assertions and numeric comparisons Add floating-point assertions, numeric comparison assertions, and Contain for enumerables Feb 19, 2026
Copilot AI requested a review from MrKWatkins February 19, 2026 23:44
@MrKWatkins MrKWatkins marked this pull request as ready for review February 20, 2026 00:57
Copy link
Owner

@MrKWatkins MrKWatkins left a comment

Choose a reason for hiding this comment

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

You didn't do these points from my list:

  1. Async Action Assertions (new type group)

ActionAssertions covers Action only. Required for async delegates (Func):

ThrowAsync<TException>() — asserts the async action throws the specified exception type
ThrowAsync<TException>(string expectedMessage) — with message check
NotThrowAsync() — asserts the async action does not throw

Should mirror the existing ActionAssertions API and chain into ExceptionAssertions.

Entry point needed in ShouldExtensions:

Should(this Func<Task> value) → AsyncActionAssertions

(2 uses, e.g. await multiEnvironment.Awaiting(m => m.StopAsync()).Should().ThrowAsync().WithMessage(...))

Also needed in InvokingExtensions:

Awaiting<T>(this T value, Func<T, Task> action) → Func<Task>

Typed NotThrow<TException>()

ActionAssertions.NotThrow() asserts no exception is thrown. There is also usage of a typed variant that asserts a specific exception type is not thrown (other exceptions may propagate):

NotThrow<TException>() — asserts the action does not throw TException specifically

(e.g. stream.Invoking(s => s.WriteByte(0)).Should().NotThrow())

Change the NotThrow methods, sync and async, for Funcs to return the result of the func afterwards to allow chaining, via a AndResult parameter. E.g. Assert.That(x => x.ToString).Should().NotThrow().And.Result.Should().NotBeNull()

…Task>), and Awaiting extensions

Co-authored-by: MrKWatkins <345796+MrKWatkins@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

You didn't do these points from my list:

  1. Async Action Assertions (new type group)...

Added in fd1d985:

  • AsyncActionAssertions with ThrowAsync<T>(), ThrowAsync<T>(string expectedMessage), and NotThrowAsync() — mirrors the ActionAssertions API and reuses ActionAssertionsChain<TException> for chaining
  • Should(this Func<Task>) in ShouldExtensions returning AsyncActionAssertions
  • Awaiting<T>(this T, Func<T, Task>) and Awaiting<T, TResult>(this T, Func<T, Task<TResult>>) in InvokingExtensions

Usage example:

await multiEnvironment.Awaiting(m => m.StopAsync()).Should().ThrowAsync<SomeException>("expected message");

Copilot AI changed the title Add floating-point assertions, numeric comparison assertions, and Contain for enumerables Add floating-point assertions, numeric comparison assertions, Contain for enumerables, and async action assertions Feb 20, 2026
Copilot AI requested a review from MrKWatkins February 20, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments