8000 [API Proposal]: Assertions to repeatedly execute an action until it succeeds · Issue #38 · AwesomeAssertions/AwesomeAssertions · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
[API Proposal]: Assertions to repeatedly execute an action until it succeeds #38
Closed as not planned
@cbersch

Description

@cbersch

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.

Metadata

Metadata

Assignees

Labels

api-needs-workAPI needs work before it is approved, it is NOT ready for implementationenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0