We would like to use Spec Flow with the Async Await Features of C#5.
SpecFlow with MSTest can execute Code using async / await but doesn t wait for the Results.
Is something planned to Support this Issue?
I don't understand.... how do you want to use async / await? In the specs themselves?
I want to execute async code in the "when step" and assert the result in a "then step"
I'd like to second this feature request, however, I certainly appreciate that it won't be a 5 minute job.
I guess the thing is... how would the framework accomplish this if the code itself was making the async call?
For example, if I fire off a side process in code that was executed in the When step, how would the Then step know how to verify for the result?
I don't think there is anything to be done in Specflow. You can maybe achieve some sort of this, by creating a Task in the when step, and wait for it in the then. I really would like to see how you expect this to work (pseudo code)
Mohamed, you're absolutely correct; async/await operations can be performed with no modification to Specflow using a Task either within or between steps (smuggling the Task via ScenarioContext). Waiting or accessing the Result of the Task will nicely block the Specflow thread until the async operation completes.
Accordingly, I withdraw my support for this unnecessary feature request.
Thanks guys.
It's no problem. :) Thank you!
A simple but helpful change to specflow would be if any step binding returned a Task, then specflow would wait for it to finish before continuing (and check for failure). See "Async Unit Tests" at http://bradwilson.typepad.com/blog/2012/01/xunit19.html
@robfe This interests me, but as someone who doesn't have a ton of experience in that -- can you give some sample code here to make it easier to see?
Well it's to allow me to write steps like:
``` C#
[When(@"I press add")]
public async Task WhenIPressAdd()
{
_result = await _calculator.Add();
}
...and be sure that _result has been set by the time the next step runs. All specflow has to do is call `task.Wait()` if the step returns a `Task`. Don't bother with handling `Task<T>` since the steps themselves don't need to return values (`void`=>`Task`, `T`=>`Task<T>`).
It would also work for steps that don't use `async`/`await` like:
``` C#
[When(@"I press add")]
public Task WhenIPressAdd()
{
return Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
_result = _numbers.Sum();
});
}
Note that when tasks' actions throw exceptions:
``` C#
[When(@"I press add")]
public Task WhenIPressAdd()
{
return Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
ScenarioContext.Current.Pending();
});
}
...then this exception isn't catchable from calling the method that returns the task, it's available as a property on the task once it finishes (this is the code i expect you'd have to have in specflow once a step finishes):
``` C#
task.Wait();
if (task.IsFaulted)
{
var error = task.Exception;
//use error to fail the step
}
It's not _really_ about testing asynchronous code, it's more about taking code that's intended to be used in an asynchronous manner (i.e. it uses Tasks and probably async/await) and making that code easy to run synchronously in your unit tests.
I went ahead an implemented this in a fork: https://github.com/robfe/SpecFlow/commit/507368327341e71b2f5e2a4a1b7757e0f4fb809d
It requires Specflow's core library to be updated to .NET 4 (because of Tasks), so i wasn't sure if you wanted a pull request?
I would pop a pull request for that.
This would be really useful.
It is becoming very common to work with async Task library code that is either being tested or verifying a test condition. We have async/await in the language to allow this async code to run seamlesly, but Specflow makes us .Wait() on every task, making it harder than necessary to read and write the test code.
Allowing us to write Task returning step definitions, and awaiting on the returned task would be very welcome, and it does not look like a very difficult modification, and there are already PRs to fix this. Why isn't this already merged in?
Second that - this useful patch from Rob should be pulled in, I've had to check out the source and apply it myself for now.
Third that, really helpful feature.
Agree this would be useful. NUnit, XUnit and BDDfy all have the equivalent capability now. It's a shame to have to pollute SpecFlow steps with unnecessary 'Wait' and 'Result' calls just to test asnyc. code.
Count me in - hope it gets added at some point
I wrote an almost all "asynced" method application. When i got to implementing the steps, i ended up using the cluttery Wait method to make my "async" app "sync". :(
So :+1: for the initiative
Everybody that has said they want this... can we get more eyeballs on the pull request tied to this ticket? https://github.com/techtalk/SpecFlow/pull/287 Someone pointed out a problem with the PR, but nobody has responded.
Or preferably, more than just eyeballs... can someone try using the PR and see if it works?
Voting is fine, but we need hands on keyboards providing some verification of a potential fix.
@darrencauthon @wied03's suggestion is less of an issue and more of a further improvement, IMO. My vote (maybe biased, since I wrote the PR) would be to move one step ahead by merging the PR and then consider @wied03's as step two.
@robfe That sounds good to me! I marked the PR as such.
@robfe So it's merged... can you try picking off the master branch and seeing how it works for you?
Hey @darrencauthon, this worked for me after compiling and hosting internally. However, it looks like this functionality is not included in BindingInvoker.cs in the v2 branch. Are you planning on adding it before final release of v2? Thanks!
This would be useful in the v2 branch as well...
Is this coming any time soon? Seems like 2.1 does not support this...
Async/Await support is in the 2.2.0-preview https://www.nuget.org/packages/SpecFlow/2.2.0-preview20161020
See this PR: https://github.com/techtalk/SpecFlow/pull/647
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Well it's to allow me to write steps like:
``` C#
[When(@"I press add")]
public async Task WhenIPressAdd()
{
_result = await _calculator.Add();
}
Note that when tasks' actions throw exceptions:
``` C#
[When(@"I press add")]
public Task WhenIPressAdd()
{
return Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
ScenarioContext.Current.Pending();
});
}
It's not _really_ about testing asynchronous code, it's more about taking code that's intended to be used in an asynchronous manner (i.e. it uses Tasks and probably async/await) and making that code easy to run synchronously in your unit tests.