Whats Specflow?
Its a library that allows for Behavior Driven Development in .NET.
(BDD) using Gherkin Syntax (Given-When-Then).
“SpecFlow helps teams bind automation to feature files and share the resulting examples as Living Documentation across the team and stakeholders. - specflow.org”
PRO - using Gherkin and Specflow allows the entire team to contribute towards the test requirements, your Product Owner or Designer may not be technical but they do understand the domain so dont discount their input.
CON - Gherkin and Specflow add additional complexity, if its just the developer writing the tests then its probably not going to add much value.
SpecFlow seems pretty focused on integration testing - Code that invokes a unit of work that crosses project boundaries, uses actual external dependencies, and/or validates many different aspects about the code under test.
As Im using Visual Studio 2019
I installed the extension SpecFlow for Visual Studio 2019.
Whats Gherkin?
Its the Syntax (Given-When-Then) which are keywords, the example below is from the template SpecFlow Project
1 | Feature: Calculator |
Specflow then knows how to translate the above into steps simliar to the classic tripple A
testing pattern.
All of the below will have using TechTalk.SpecFlow;
this resolves the annotations Given When Then
above the methods.
If you place your cursor on a line in the .feature
and press F12 (Go to definition) the IDE should navigate to the correct place in the step as shown in CalculatorStepDefinitions.cs
below.
Arrange
1 | // Given the first number is 50 |
Additional Arrange
steps are added with the keyword And
:
1 | // And the second number is 70 |
Act
1 | // When the two numbers are added |
Assert
The assertion can be done with any testing framework or the SpecFlow+ Runner.
1 | // Then the result should be 120 |
Sweet how do I set things up?
The flow is simply and there are awesome getting started guides like Getting Started With An Example and Getting Started With A New Project.
A summary of the core steps are with a new project are:
- Create new project from template
SpecFlow Project
- This creates /Features/Calculator.feature
- It also create /Steps/CalculatorStepDefinitions.cs
- Create the
Example
Project, this is the code you want to test, following their example its aclass library
. EACH LINE in theScenario
needs to be satisfied with c# code:-
public void GivenTheFirstNumberIs(int number)
, this sets (arrange) the stateFirstNumber
-
public void GivenTheSecondNumberIs(int number)
this sets (arrange) the state forSecondNumber
-
public void WhenTheTwoNumbersAreAdded()
this calls some behaviour (act) :_calculator.Add();
-
public void ThenTheResultShouldBe(int expectedResult)
asserts the result
-
Scenario Context
The boilerplate code injected ScenarioContext _scenarioContext;
into the constructor in CalculatorStepDefinitions.cs
“ScenarioContext helps you store values in a dictionary between steps. This helps you to organize your step definitions better than using private variables in step definition classes. -docs.specflow.org”
This means we call things like
1 | _scenarioContext.Add ~ add new key/value |
They also have something called Context-Injection
“This feature allows you to group the shared state in context classes, and inject them into every binding class that needs access to that shared state. -docs.specflow.org”
To use context injection:
- Create your POCOs (simple .NET classes) representing the shared data.
- Define them as constructor parameters in every binding class that requires them.
- Save the constructor argument to instance fields, so you can use them in the step definitions.
This means CalculatorStepDefinitions
could be changed from creating its own new Calculator();
1 | private readonly ScenarioContext _scenarioContext; |
To automagically injecting an instance based on the default constructor
1 | private readonly Calculator _calculator; |
Feature Context
“FeatureContext persists for the duration of the execution of an entire feature, whereas ScenarioContext only persists for the duration of a scenario. -docs.specflow.org”
These are useful hooks as you can have annotations like [BeforeFeature]
and [AfterFeature]
.
Note that hooks also exist for Scenario Context
: [BeforeScenario]
and [AfterScenario]
.
You can use either to rebind/override IKernel
with your own mock implementations.
Example from docs.specflow.or:
1 | [ ] |
References
- https://github.com/carlpaton/SpecFlowDemo
- https://specflow.org/
- https://docs.specflow.org/projects/specflow/en/latest/Getting-Started/Getting-Started-With-An-Example.html
- https://docs.specflow.org/projects/specflow/en/latest/Getting-Started/Getting-Started-With-A-New-Project.html
- https://cucumber.io/docs/gherkin/reference/
- https://docs.specflow.org/projects/specflow/en/latest/Gherkin/Gherkin-Reference.html