Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ExecutionTime acception async action #938

Merged
merged 1 commit into from Oct 7, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 15 additions & 2 deletions Src/FluentAssertions/AssertionExtensions.cs
Expand Up @@ -55,9 +55,9 @@ public static MemberExecutionTime<T> ExecutionTimeOf<T>(this T subject, Expressi
}

/// <summary>
/// Provides methods for asserting the execution time of a method or property.
/// Provides methods for asserting the execution time of an action.
/// </summary>
/// <param name="action">A reference to the method or property to measure the execution time of.</param>
/// <param name="action">An action to measure the execution time of.</param>
/// <returns>
/// Returns an object for asserting that the execution time matches certain conditions.
/// </returns>
Expand All @@ -67,6 +67,19 @@ public static ExecutionTime ExecutionTime(this Action action)
return new ExecutionTime(action);
}

/// <summary>
/// Provides methods for asserting the execution time of an async action.
/// </summary>
/// <param name="action">An async action to measure the execution time of.</param>
/// <returns>
/// Returns an object for asserting that the execution time matches certain conditions.
/// </returns>
[MustUseReturnValue /* do not use Pure because this method executes the action before returning to the caller */]
public static ExecutionTime ExecutionTime(this Func<Task> action)
{
return new ExecutionTime(action);
}

/// <summary>
/// Returns an <see cref="ExecutionTimeAssertions"/> object that can be used to assert the
/// current <see cref="ExecutionTime"/>.
Expand Down
37 changes: 37 additions & 0 deletions Src/FluentAssertions/Specialized/ExecutionTimeAssertions.cs
Expand Up @@ -220,6 +220,11 @@ public ExecutionTime(Action action)
{
}

public ExecutionTime(Func<Task> action)
: this(action, "the action")
{
}

protected ExecutionTime(Action action, string actionDescription)
{
ActionDescription = actionDescription;
Expand Down Expand Up @@ -247,6 +252,38 @@ protected ExecutionTime(Action action, string actionDescription)
});
}

/// <remarks>
/// This constructor is almost exact copy of the one accepting <see cref="Action"/>.
/// The original constructor shall stay in place in order to keep backward-compatibility
/// and to avoid unnecessary wrapping action in <see cref="Task"/>.
/// </remarks>
protected ExecutionTime(Func<Task> action, string actionDescription)
krajek marked this conversation as resolved.
Show resolved Hide resolved
{
ActionDescription = actionDescription;
stopwatch = new Stopwatch();
IsRunning = true;
Task = Task.Run(async () =>
{
// move stopwatch as close to action start as possible
// so that we have to get correct time readings
try
{
stopwatch.Start();
await action();
}
catch (Exception exception)
{
Exception = exception;
}
finally
{
// ensures that we stop the stopwatch even on exceptions
stopwatch.Stop();
IsRunning = false;
}
});
}

internal TimeSpan ElapsedTime => stopwatch.Elapsed;

internal bool IsRunning { get; private set; }
Expand Down
43 changes: 42 additions & 1 deletion Tests/Shared.Specs/ExecutionTimeAssertionsSpecs.cs
@@ -1,6 +1,6 @@
using System;
using System.Threading;

using System.Threading.Tasks;
using FluentAssertions.Extensions;
using Xunit;
using Xunit.Sdk;
Expand Down Expand Up @@ -179,6 +179,27 @@ public void When_the_execution_time_of_an_action_is_not_less_than_a_limit__it_sh
"*action should be less than 0.100s, but it required*");
}

[Fact]
public void When_the_execution_time_of_an_async_action_is_not_less_than_a_limit__it_should_throw()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------

Func<Task> someAction = async () => await Task.Delay(TimeSpan.FromMilliseconds(150));

//-----------------------------------------------------------------------------------------------------------
// Act
//-----------------------------------------------------------------------------------------------------------
Action act = () => someAction.ExecutionTime().Should().BeLessThan(100.Milliseconds());

//-----------------------------------------------------------------------------------------------------------
// Assert
//-----------------------------------------------------------------------------------------------------------
act.Should().Throw<XunitException>().WithMessage(
"*action should be less than 0.100s, but it required*");
}

[Fact]
public void When_the_execution_time_of_an_action_is_less_than_a_limit_it_should_not_throw()
{
Expand All @@ -199,6 +220,26 @@ public void When_the_execution_time_of_an_action_is_less_than_a_limit_it_should_
act.Should().NotThrow();
}

[Fact]
public void When_the_execution_time_of_an_async_action_is_less_than_a_limit_it_should_not_throw()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------

Func<Task> someAction = async () => await Task.Delay(TimeSpan.FromMilliseconds(100));

//-----------------------------------------------------------------------------------------------------------
// Act
//-----------------------------------------------------------------------------------------------------------
Action act = () => someAction.ExecutionTime().Should().BeLessThan(1.Seconds());

//-----------------------------------------------------------------------------------------------------------
// Assert
//-----------------------------------------------------------------------------------------------------------
act.Should().NotThrow();
}

[Fact]
public void When_action_runs_indefinitely_it_should_be_stopped_and_throw_if_there_is_less_than_condition()
{
Expand Down