Screenplay & Reqnroll tutorial
Tip
Are you using the legacy SpecFlow? Reqnroll is the maintained fork of SpecFlow, so it's recommended you upgrade your projects ASAP.
For now, CSF.Screenplay continues to support SpecFlow. Use the CSF.Screenplay.SpecFlow package and SpecFlow v3.4.3 or higher instead. The remainder of the instructions below work for either Reqnroll or SpecFlow.
Begin writing Reqnroll tests using Screenplay by following these steps. Further detail is provided below.
- Ensure that your test project uses Reqnroll version 2.0.0 or higher
- Install the NuGet package CSF.Screenplay.Reqnroll to the project which will contain your
.featurefiles - Optional: Add services to dependency injection which will be required by the Abilities you intend to use. If required, use Reqnroll context injection & hooks to add these to the DI container.
- Write step binding classes which dependency-inject and use Screenplay's architecture
Writing step bindings
Important
When using Reqnroll with Screenplay, every Screenplay-using test within a test assembly (thus, within a .NET project) must share the same instance of Screenplay.
This is not expected to be problematic, as all the Screenplay object does is set-up the Screenplay architecture and dependency injection for the tests.
When using Screenplay with Reqnroll, .feature files are written as normal.
The only difference in writing your tests is that Step Binding classes should inject Screenplay architecture and use it within the bindings.
The recommended services to inject into your step binding classes are either IStage or ICast.
If you are using Personas, which are the recommended way to get Actors for your performances, then most step binding classes will need only one of the two services above.
If you are not using Personas to get actors, then you might also need to inject some services which relate to the Abilities that you wish to grant actors.
Example
Tip
The implied ability, the performables, persona and DishwashingBuilder used in this test, related to washing dishes, are all fictitious.
See the documentation for writing performables to learn about how these could be written.
This example assumes that Reqnroll is writting using the NUnit runner, and thus it makes use of NUnit-style assertions. Feel free to replace the assertion with whichever assertion library you wish to use.
using CSF.Screenplay;
using static CSF.Screenplay.PerformanceStarter;
using static WashingTheDishes.DishwashingBuilder;
[Binding]
public class WashTheDishesSteps(IStage stage)
{
[Given(@"^Joe was able to get some dirty dishes$")]
public async Task GetDirtyDishes()
{
var joe = stage.Spotlight<Joe>();
await Given(joe).WasAbleTo(GetSomeDirtyDishes());
}
[When(@"^(?:he|she|they) attempts? to wash the dishes$")]
public async Task WashTheDishes()
{
var actor = stage.GetSpotlitActor();
await When(actor).AttemptsTo(WashTheDishes());
}
[Then(@"^(?:he|she|they) should see that the dishes are clean$")]
public async Task GetDirtyDishes()
{
var actor = stage.GetSpotlitActor();
var condition = await Then(actor).Should(LookAtTheDishesCondition());
Assert.That(condition, Is.EqualTo("Clean"));
}
}