Skip to content

feat: add IsBetween for TimeSpan#623

Merged
vbreuss merged 1 commit intomainfrom
topic/add-isbetween-for-timespan
May 20, 2025
Merged

feat: add IsBetween for TimeSpan#623
vbreuss merged 1 commit intomainfrom
topic/add-isbetween-for-timespan

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented May 20, 2025

Adds support for “between” assertions on TimeSpan (and nullable) with optional tolerance.

  • Introduces IsBetween and IsNotBetween APIs and their constraint implementations
  • Adds comprehensive unit tests covering edge cases and tolerance behavior
  • Updates API surface expectations and documentation to reflect new methods

Between

You can verify that the TimeSpan is between two values:

TimeSpan subject = TimeSpan.FromSeconds(42);

await Expect.That(subject).IsBetween(TimeSpan.FromSeconds(40)).And(TimeSpan.FromSeconds(50));

You can also specify a tolerance:

TimeSpan subject = TimeSpan.FromSeconds(42);

await Expect.That(subject)
	.IsBetween(43.Seconds())
    .And(45.Seconds())
	.Within(1.Seconds())
  .Because("it should expand the interval by 1 second");

## Between

You can verify that the `TimeSpan` is between two values:

```csharp
TimeSpan subject = TimeSpan.FromSeconds(42);

await Expect.That(subject).IsBetween(TimeSpan.FromSeconds(40)).And(TimeSpan.FromSeconds(50));
```

You can also specify a tolerance:

```csharp
TimeSpan subject = TimeSpan.FromSeconds(42);

await Expect.That(subject)
	.IsBetween(43.Seconds())
    .And(45.Seconds())
	.Within(1.Seconds())
  .Because("it should expand the interval by 1 second");
```
@vbreuss vbreuss self-assigned this May 20, 2025
Copilot AI review requested due to automatic review settings May 20, 2025 14:34
@vbreuss vbreuss added the enhancement New feature or request label May 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

Adds support for “between” assertions on TimeSpan (and nullable) with optional tolerance.

  • Introduces IsBetween and IsNotBetween APIs and their constraint implementations
  • Adds comprehensive unit tests covering edge cases and tolerance behavior
  • Updates API surface expectations and documentation to reflect new methods

Reviewed Changes

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

Show a summary per file
File Description
Source/aweXpect/That/TimeSpans/ThatTimeSpan.IsBetween.cs Implements IsBetween/IsNotBetween for TimeSpan
Source/aweXpect/That/TimeSpans/ThatNullableTimeSpan.IsBetween.cs Implements nullable overloads for the same APIs
Tests/aweXpect.Tests/TimeSpans/ThatTimeSpan.Nullable.IsNotBetween.Tests.cs New tests for nullable IsNotBetween behavior
Tests/aweXpect.Tests/TimeSpans/ThatTimeSpan.Nullable.IsBetween.Tests.cs New tests for nullable IsBetween behavior
Tests/aweXpect.Tests/TimeSpans/ThatTimeSpan.IsNotBetween.Tests.cs New tests for non-nullable IsNotBetween behavior
Tests/aweXpect.Tests/TimeSpans/ThatTimeSpan.IsBetween.Tests.cs New tests for non-nullable IsBetween behavior
Tests/aweXpect.Core.Tests/Customization/CustomizeSettingsTests.cs Adjusts expected default timeout via #if DEBUG
Tests/aweXpect.Api.Tests/Expected/aweXpect_netstandard2.0.txt Adds new method signatures for .NET Standard 2.0
Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt Adds new method signatures for .NET 8.0
Docs/pages/docs/expectations/10-timespan.md Documents the new “Between” section
Comments suppressed due to low confidence (2)

Tests/aweXpect.Tests/TimeSpans/ThatTimeSpan.Nullable.IsNotBetween.Tests.cs:110

  • [nitpick] The test name implies the subject is not between the bounds, but in this scenario the subject is between them. Consider renaming to WhenSubjectIsBetweenMinimumAndMaximum_ShouldFail for clarity.
public async Task WhenSubjectIsNotBetweenMinimumAndMaximum_ShouldFail()

Tests/aweXpect.Tests/TimeSpans/ThatTimeSpan.IsNotBetween.Tests.cs:82

  • [nitpick] This test name suggests the subject is outside the range, but the subject is actually between. Rename to WhenSubjectIsBetweenMinimumAndMaximum_ShouldFail to match the scenario.
public async Task WhenSubjectIsNotBetweenMinimumAndMaximum_ShouldFail()

Comment thread Tests/aweXpect.Core.Tests/Customization/CustomizeSettingsTests.cs
@sonarqubecloud
Copy link
Copy Markdown

@vbreuss vbreuss enabled auto-merge (squash) May 20, 2025 14:38
@vbreuss vbreuss disabled auto-merge May 20, 2025 14:40
@vbreuss vbreuss enabled auto-merge (squash) May 20, 2025 14:40
@github-actions
Copy link
Copy Markdown
Contributor

Test Results

    14 files   -  24      14 suites   - 24   2m 26s ⏱️ +16s
10 608 tests + 37  10 606 ✅ + 37  2 💤 ±0  0 ❌ ±0 
28 866 runs  +108  28 864 ✅ +108  2 💤 ±0  0 ❌ ±0 

Results for commit f338215. ± Comparison against base commit 67d0ad6.

@vbreuss vbreuss merged commit 905faa4 into main May 20, 2025
13 checks passed
@vbreuss vbreuss deleted the topic/add-isbetween-for-timespan branch May 20, 2025 14:44
@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.409
[Host] : .NET 8.0.16 (8.0.1625.21506), X64 RyuJIT AVX2

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

Method Mean Error StdDev Gen0 Gen1 Allocated
Bool_aweXpect 187.7 ns 1.40 ns 1.24 ns 0.0281 - 472 B
Bool_FluentAssertions 257.3 ns 3.20 ns 2.99 ns 0.0567 - 952 B
Bool_TUnit 939.1 ns 7.88 ns 6.99 ns 0.1440 - 2416 B
Equivalency_aweXpect 305,023.7 ns 1,130.53 ns 882.65 ns 16.6016 0.4883 284940 B
Equivalency_FluentAssertions 2,390,432.8 ns 19,784.51 ns 18,506.44 ns 273.4375 46.8750 4584416 B
Equivalency_TUnit 690,704.8 ns 3,752.03 ns 3,509.66 ns 51.7578 2.9297 866777 B
Int_GreaterThan_aweXpect 229.9 ns 3.05 ns 2.86 ns 0.0467 - 784 B
Int_GreaterThan_FluentAssertions 270.4 ns 3.71 ns 3.47 ns 0.0730 - 1224 B
Int_GreaterThan_TUnit 1,289.6 ns 14.35 ns 13.42 ns 0.1774 - 2992 B
ItemsCount_AtLeast_aweXpect 462.2 ns 3.80 ns 3.37 ns 0.0830 - 1392 B
ItemsCount_AtLeast_FluentAssertions 507.5 ns 10.16 ns 9.50 ns 0.1192 - 2008 B
ItemsCount_AtLeast_TUnit 17,356.5 ns 107.00 ns 94.85 ns 1.6174 - 27488 B
String_aweXpect 360.4 ns 3.47 ns 3.25 ns 0.0672 - 1128 B
String_FluentAssertions 510.8 ns 6.53 ns 6.11 ns 0.1287 - 2168 B
String_TUnit 1,356.7 ns 10.93 ns 10.22 ns 0.1850 - 3096 B
StringArray_aweXpect 1,174.0 ns 5.54 ns 5.18 ns 0.1202 - 2024 B
StringArray_FluentAssertions 1,367.2 ns 16.19 ns 15.14 ns 0.2480 - 4152 B
StringArray_TUnit 2,934.2 ns 11.40 ns 10.66 ns 0.2708 - 4576 B
StringArrayInAnyOrder_aweXpect 1,389.0 ns 5.90 ns 5.23 ns 0.1297 - 2184 B
StringArrayInAnyOrder_FluentAssertions 152,138.8 ns 1,183.69 ns 1,107.22 ns 3.4180 - 63351 B
StringArrayInAnyOrder_TUnit 4,877.3 ns 29.68 ns 27.76 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/TimeSpans/ThatNullableTimeSpan.IsBetween.cs 88.64% 39 2 0 3 6 0 39 5 50
That/TimeSpans/ThatTimeSpan.IsBetween.cs 100.00% 35 0 0 0 6 0 35 0 41

The final mutation score is 93.67%

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

github-actions Bot added a commit that referenced this pull request May 20, 2025
github-actions Bot added a commit that referenced this pull request May 20, 2025
@github-actions
Copy link
Copy Markdown
Contributor

This is addressed in release v2.14.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