Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Docs/pages/docs/expectations/10-timespan.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ await Expect.That(subject).IsLessThan(42).Within(TimeSpan.FromSeconds(2))
.Because("we accept values less than 0:44 (0:42 ± 2s)");
```

## 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");
```

## Positive / negative

You can verify that the `TimeSpan` is positive or negative:
Expand Down
109 changes: 109 additions & 0 deletions Source/aweXpect/That/TimeSpans/ThatNullableTimeSpan.IsBetween.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System;
using aweXpect.Core;
using aweXpect.Core.Constraints;
using aweXpect.Customization;
using aweXpect.Helpers;
using aweXpect.Options;
using aweXpect.Results;

namespace aweXpect;

public static partial class ThatNullableTimeSpan
{
/// <summary>
/// Verifies that the subject is between the <paramref name="minimum" />…
/// </summary>
public static BetweenResult<TimeToleranceResult<TimeSpan?, IThat<TimeSpan?>>, TimeSpan?> IsBetween(
this IThat<TimeSpan?> source,
TimeSpan? minimum)
{
TimeTolerance tolerance = new();
return new BetweenResult<TimeToleranceResult<TimeSpan?, IThat<TimeSpan?>>, TimeSpan?>(maximum
=> new TimeToleranceResult<TimeSpan?, IThat<TimeSpan?>>(
source.Get().ExpectationBuilder.AddConstraint((it, grammars) =>
new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance)),
source,
tolerance));
}

/// <summary>
/// Verifies that the subject is not between the <paramref name="minimum" />…
/// </summary>
public static BetweenResult<TimeToleranceResult<TimeSpan?, IThat<TimeSpan?>>, TimeSpan?> IsNotBetween(
this IThat<TimeSpan?> source,
TimeSpan? minimum)
{
TimeTolerance tolerance = new();
return new BetweenResult<TimeToleranceResult<TimeSpan?, IThat<TimeSpan?>>, TimeSpan?>(maximum
=> new TimeToleranceResult<TimeSpan?, IThat<TimeSpan?>>(
source.Get().ExpectationBuilder.AddConstraint((it, grammars) =>
new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance).Invert()),
source,
tolerance));
}

private sealed class IsBetweenConstraint(
string it,
ExpectationGrammars grammars,
TimeSpan? minimum,
TimeSpan? maximum,
TimeTolerance tolerance)
: ConstraintResult.WithNotNullValue<TimeSpan?>(it, grammars),
IValueConstraint<TimeSpan?>
{
public ConstraintResult IsMetBy(TimeSpan? actual)
{
Actual = actual;
if (actual is null && minimum is null && maximum is null)
{
Outcome = Outcome.Success;
}
else if (actual is null || minimum is null || maximum is null)
{
Outcome = IsNegated ? Outcome.Success : Outcome.Failure;
}
else
{
TimeSpan timeTolerance = tolerance.Tolerance
?? Customize.aweXpect.Settings().DefaultTimeComparisonTolerance.Get();
if (IsNegated)
{
timeTolerance = timeTolerance.Negate();
}

Outcome = actual.Value.Add(timeTolerance) >= minimum && actual.Value.Add(timeTolerance.Negate()) <= maximum
? Outcome.Success
: Outcome.Failure;
}

return this;
}

protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null)
{
stringBuilder.Append("is between ");
Formatter.Format(stringBuilder, minimum);
stringBuilder.Append(" and ");
Formatter.Format(stringBuilder, maximum);
stringBuilder.Append(tolerance);
}

protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null)
{
stringBuilder.Append(It).Append(" was ");
Formatter.Format(stringBuilder, Actual);
}

protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null)
{
stringBuilder.Append("is not between ");
Formatter.Format(stringBuilder, minimum);
stringBuilder.Append(" and ");
Formatter.Format(stringBuilder, maximum);
stringBuilder.Append(tolerance);
}

protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null)
=> AppendNormalResult(stringBuilder, indentation);
}
}
105 changes: 105 additions & 0 deletions Source/aweXpect/That/TimeSpans/ThatTimeSpan.IsBetween.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using aweXpect.Core;
using aweXpect.Core.Constraints;
using aweXpect.Customization;
using aweXpect.Helpers;
using aweXpect.Options;
using aweXpect.Results;

namespace aweXpect;

public static partial class ThatTimeSpan
{
/// <summary>
/// Verifies that the subject is between the <paramref name="minimum" />…
/// </summary>
public static BetweenResult<TimeToleranceResult<TimeSpan, IThat<TimeSpan>>, TimeSpan?> IsBetween(
this IThat<TimeSpan> source,
TimeSpan? minimum)
{
TimeTolerance tolerance = new();
return new BetweenResult<TimeToleranceResult<TimeSpan, IThat<TimeSpan>>, TimeSpan?>(maximum
=> new TimeToleranceResult<TimeSpan, IThat<TimeSpan>>(
source.Get().ExpectationBuilder.AddConstraint((it, grammars) =>
new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance)),
source,
tolerance));
}

/// <summary>
/// Verifies that the subject is not between the <paramref name="minimum" />…
/// </summary>
public static BetweenResult<TimeToleranceResult<TimeSpan, IThat<TimeSpan>>, TimeSpan?> IsNotBetween(
this IThat<TimeSpan> source,
TimeSpan? minimum)
{
TimeTolerance tolerance = new();
return new BetweenResult<TimeToleranceResult<TimeSpan, IThat<TimeSpan>>, TimeSpan?>(maximum
=> new TimeToleranceResult<TimeSpan, IThat<TimeSpan>>(
source.Get().ExpectationBuilder.AddConstraint((it, grammars) =>
new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance).Invert()),
source,
tolerance));
}

private sealed class IsBetweenConstraint(
string it,
ExpectationGrammars grammars,
TimeSpan? minimum,
TimeSpan? maximum,
TimeTolerance tolerance)
: ConstraintResult.WithNotNullValue<TimeSpan>(it, grammars),
IValueConstraint<TimeSpan>
{
public ConstraintResult IsMetBy(TimeSpan actual)
{
Actual = actual;
if (minimum is null || maximum is null)
{
Outcome = IsNegated ? Outcome.Success : Outcome.Failure;
}
else
{
TimeSpan timeTolerance = tolerance.Tolerance
?? Customize.aweXpect.Settings().DefaultTimeComparisonTolerance.Get();
if (IsNegated)
{
timeTolerance = timeTolerance.Negate();
}

Outcome = actual.Add(timeTolerance) >= minimum && actual.Add(timeTolerance.Negate()) <= maximum
? Outcome.Success
: Outcome.Failure;
}

return this;
}

protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null)
{
stringBuilder.Append("is between ");
Formatter.Format(stringBuilder, minimum);
stringBuilder.Append(" and ");
Formatter.Format(stringBuilder, maximum);
stringBuilder.Append(tolerance);
}

protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null)
{
stringBuilder.Append(It).Append(" was ");
Formatter.Format(stringBuilder, Actual);
}

protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null)
{
stringBuilder.Append("is not between ");
Formatter.Format(stringBuilder, minimum);
stringBuilder.Append(" and ");
Formatter.Format(stringBuilder, maximum);
stringBuilder.Append(tolerance);
}

protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null)
=> AppendNormalResult(stringBuilder, indentation);
}
}
4 changes: 4 additions & 0 deletions Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -653,12 +653,14 @@ namespace aweXpect
}
public static class ThatNullableTimeSpan
{
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>>, System.TimeSpan?> IsBetween(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsGreaterThan(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsLessThan(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsLessThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.AndOrResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNegative(this aweXpect.Core.IThat<System.TimeSpan?> source) { }
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>>, System.TimeSpan?> IsNotBetween(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNotEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNotGreaterThan(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNotGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? unexpected) { }
Expand Down Expand Up @@ -881,12 +883,14 @@ namespace aweXpect
}
public static class ThatTimeSpan
{
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>>, System.TimeSpan?> IsBetween(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsGreaterThan(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsLessThan(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsLessThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.AndOrResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNegative(this aweXpect.Core.IThat<System.TimeSpan> source) { }
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>>, System.TimeSpan?> IsNotBetween(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNotEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNotGreaterThan(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNotGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? unexpected) { }
Expand Down
4 changes: 4 additions & 0 deletions Tests/aweXpect.Api.Tests/Expected/aweXpect_netstandard2.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -469,12 +469,14 @@ namespace aweXpect
}
public static class ThatNullableTimeSpan
{
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>>, System.TimeSpan?> IsBetween(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsGreaterThan(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsLessThan(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsLessThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? expected) { }
public static aweXpect.Results.AndOrResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNegative(this aweXpect.Core.IThat<System.TimeSpan?> source) { }
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>>, System.TimeSpan?> IsNotBetween(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNotEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNotGreaterThan(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan?, aweXpect.Core.IThat<System.TimeSpan?>> IsNotGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan?> source, System.TimeSpan? unexpected) { }
Expand Down Expand Up @@ -928,12 +930,14 @@ namespace aweXpect
}
public static class ThatTimeSpan
{
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>>, System.TimeSpan?> IsBetween(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsGreaterThan(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsLessThan(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsLessThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? expected) { }
public static aweXpect.Results.AndOrResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNegative(this aweXpect.Core.IThat<System.TimeSpan> source) { }
public static aweXpect.Results.BetweenResult<aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>>, System.TimeSpan?> IsNotBetween(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? minimum) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNotEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNotGreaterThan(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? unexpected) { }
public static aweXpect.Results.TimeToleranceResult<System.TimeSpan, aweXpect.Core.IThat<System.TimeSpan>> IsNotGreaterThanOrEqualTo(this aweXpect.Core.IThat<System.TimeSpan> source, System.TimeSpan? unexpected) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ public sealed class CustomizeSettingsTests
[Fact]
public async Task DefaultCheckInterval_ShouldBeUsedInTimeComparisons()
{
#if DEBUG
TimeSpan timeout = 2.Seconds();
#else
TimeSpan timeout = 4.Seconds();
#endif
Comment thread
vbreuss marked this conversation as resolved.

ChangingClass sut1 = new();
ChangingClass sut2 = new();

Expand Down
Loading