Closed as not planned
Closed as not planned
Description
Background and motivation
I frequently need some kind of testing functionality to wait until a certain condition is fulfilled (similar to awaitility.org).
That could be an addition to the CompleteWithinAsync
functionality.
API Proposal
/// ReferenceTypeAssertions
public async Task<AndConstraint<TAssertions>> SatisfyWithinAsync<T>(Action<T> assertion, TimeSpan timeOut)
where T : TSubject
public async Task<AndConstraint<TAssertions>> SatisfyWithinAsync<T>(Action<T> assertion, TimeSpan timeOut, IPollingInterval pollingInterval)
where T : TSubject
/// NonGenericAsyncFunctionAssertions
public async Task<AndConstraint<NonGenericAsyncFunctionAssertions>> SucceedWithinAsync(
TimeSpan timeSpan, string because = "", params object[] becauseArgs);
public async Task<AndConstraint<NonGenericAsyncFunctionAssertions>> SucceedWithinAsync(
TimeSpan timeSpan, IPollingInterval pollingInterval, string because = "", params object[] becauseArgs);
/// GenericAsyncFunctionAssertions
public async Task<AndWhichConstraint<GenericAsyncFunctionAssertions<TResult>, TResult>> SucceedWithinAsync(
TimeSpan timeSpan, string because = "", params object[] becauseArgs);
public async Task<AndWhichConstraint<GenericAsyncFunctionAssertions<TResult>, TResult>> SucceedWithinAsync(
TimeSpan timeSpan, IPollingInterval pollingInterval, string because = "", params object[] becauseArgs);
/// FunctionAssertions
public async Task<AndWhichConstraint<FunctionAssertions<TResult>, TResult>> SucceedWithinAsync(
TimeSpan timeSpan, string because = "", params object[] becauseArgs);
public async Task<AndConstraint<FunctionAssertions>> SucceedWithinAsync(
TimeSpan timeSpan, IPollingInterval pollingInterval, string because = "", params object[] becauseArgs);
/// ActionAssertions
public async Task<AndConstraint<ActionAssertions>> SucceedWithinAsync(
TimeSpan timeSpan, string because = "", params object[] becauseArgs);
public async Task<AndConstraint<ActionAssertions>> SucceedWithinAsync(
TimeSpan timeSpan, IPollingInterval pollingInterval, string because = "", params object[] becauseArgs);
public interface IPollingInterval
{
TimeSpan NextWaitingDuration();
}
/// <summary>
/// Always returns the same fixed waiting time.
/// </summary>
internal class FixedPollingInterval : IPollingInterval
/// <summary>
/// Returns an increasing waiting time (modelled e.g. with Fibonacci sequence)
/// </summary>
internal class IncreasingPollingInterval : IPollingInterval
public static IPollingInterval FixedPolling(this TimeSpan waitingTime) =>
new FixedPollingInterval(waitingTime);
public static IPollingInterval IncreasingPolling(this TimeSpan initialWaitingTime) =>
new FixedPollingInterval(waitingTime);
API Usage
Example 1:
int i = 0;
Task Increment() => Task.FromResult(i++.Should().Be(27));
Increment.Should().SucceedWithinAsync(100.Milliseconds())
Example 2:
public sealed class BackgroundService
{
public bool Initialized { get; }
public BackgroundService()
{
_ = Task.Run(() =>
{
await Task.Delay(TimeSpan.FromSeconds(5));
Initialized = true;
};
}
}
BackgroundService instance = new();
instance.Should().SatisfyWithinAsync(
x => x.Initialized.Should().BeTrue(),
10.Seconds(),
1.Seconds().FixedPolling());
Alternative Designs
No response
Risks
No risks, this does not touch existing API.
Are you willing to help with a proof-of-concept (as PR in that or a separate repo) first and as pull-request later on?
Yes, please assign this issue to me.