Table of Contents

Class WithinTimeBudgetAssertion<T>

Namespace
TimeAssertions.TUnit
Assembly
TimeAssertions.TUnit.dll

TUnit assertion that imposes a wall-clock timing budget on the preceding assertion source. Generates the WithinTimeBudget(TimeSpan) chain extension via TUnit's TUnit.Assertions.Attributes.AssertionExtensionAttribute source generator.

[AssertionExtension("WithinTimeBudget")]
public sealed class WithinTimeBudgetAssertion<T> : Assertion<T>, IAssertion

Type Parameters

T

The value type of the underlying assertion. Inferred at the call site when chained via .And.WithinTimeBudget(...) after a behavioural assertion.

Inheritance
Assertion<T>
WithinTimeBudgetAssertion<T>
Implements
IAssertion
Inherited Members
Assertion<T>.AssertAsync()
Assertion<T>.GetAwaiter()
Assertion<T>.And
Assertion<T>.Or

Remarks

Canonical chain pattern: place .WithinTimeBudget() after .And on a behavioural assertion. The .And continuation returns IAssertionSource<T>, so the source generator's emitted WithinTimeBudget<T>(this IAssertionSource<T>, ...) extension binds with type inference:

await Assert.That(asyncOp)
    .IsEqualTo(42)
    .And.WithinTimeBudget(TimeSpan.FromMilliseconds(500));

Post-facto check, NOT cancellation. The wall-clock duration captured by TUnit's TUnit.Assertions.Core.EvaluationMetadata<TValue>.Duration is compared against the budget after the assertion's evaluator has run; the assertion is not cancelled mid-flight. This decouples TimeAssertions from TUnit's assertion lifecycle internals and avoids overlap with each sibling package's domain-specific timeout API.

For polling / streaming workloads, use the package's own timeout API (e.g. LogAssertions.WithinTimeout): .WithinTimeBudget() would let an unbounded poll run and only flag the overrun at the end.

External cancellation propagates intact. When the wrapped operation's CancellationToken cancels (parent [Timeout], test-class CT, runner cancel), the OperationCanceledException propagates through this assertion to the test runner via ExceptionDispatchInfo without being wrapped as an assertion failure. The test is recorded as cancelled, not failed. Non-OCE source exceptions continue to surface as Failed(string).

Constructors

WithinTimeBudgetAssertion(AssertionContext<T>, TimeSpan)

Initialises the assertion with a wall-clock budget. Called by the TUnit source generator.

public WithinTimeBudgetAssertion(AssertionContext<T> context, TimeSpan budget)

Parameters

context AssertionContext<T>

The assertion context supplied by TUnit.

budget TimeSpan

The maximum wall-clock duration the preceding assertion's evaluator is allowed to take.

Exceptions

ArgumentOutOfRangeException

budget is negative.

Methods

CheckAsync(EvaluationMetadata<T>)

Implements the specific check logic for this assertion. Called after the context has been evaluated. Override this method if your assertion uses the default AssertAsync() flow. If you override AssertAsync() with custom logic (like AndAssertion/OrAssertion), you don't need to implement this.

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<T> metadata)

Parameters

metadata EvaluationMetadata<T>

Metadata about the evaluation including value, exception, and timing information

Returns

Task<AssertionResult>

The result of the assertion check

GetExpectation()

Gets a human-readable description of what this assertion expects. Used in error messages.

protected override string GetExpectation()

Returns

string