Part 2 – Implementing Scenarios and Step Definitions in Specflow
In this article, we will look at how programmers use scenarios that are written in ubiquitous language to implement and test the functionality once the initial requirement-gathering stage is complete. I’ll illustrate it using an example scenario of the Coding Club case study.
In the last BDD article, we discussed the importance of using ubiquitous language and how it makes sure that everyone who is involved in the development project, from programmers to business analysts, are on the same page right from the beginning when the requirements are gathered. In this article, we’ll continue to use the ‘Coding Club’ case study that we adopted in order to illustrate how to create scenarios at the requirement-gathering phase. We’ll now show how it can be used by both programmers and testers, and finally used as the criteria during user-acceptance testing.
There are a number of tools out there that enable programmers to turn these scenarios into tests. In this case study, we will be using a tool called Specflow. Using this tool, we will show how the scenarios are converted by a programmer into executable criteria. More information on Specflow is available on http://www.specflow.org/
Features and Steps
Before we proceed to an example, we’ll need to explain what we mean by features and steps.
We will explain those terms by using Dan North’s template for scenarios that we can use for our Coding Club application:
The Title and the Narrative are referred to as Features and the text blocks that come after the Given, When, Then keywords are referred to as steps. We will use these steps to generate Step Definitions, which will be the C# code equivalent. Although steps are put together during requirement gathering and used during UAT, step definitions are generated when the programmer implements the requirements in code.
We will now illustrate how to use Specflow to implement features and step definitions. These ‘Step definitions’, as the name suggests, are simply the code implementation of the steps.
Specflow can be set up using a NuGet package in Visual Studio. There is some excellent documentation on the setup process on the Specflow website, so I don’t have to explain how to do it here.
Firstly, we need to create a Feature file. The name will describe the feature itself and will have a .feature extension (see Figure A).
After this, the next step is to add the feature and the scenarios (as shown in Figure B). You can see that the declarative language keywords (Scenario, Given, And, When, Then) are highlighted
In the list of items shown in Figure A earlier, one of the items is ‘SpecFlow Step Definition‘, which is what we want to add next. However, Specflow provides an easy way of generating Step Definitions. This can be achieved by right-clicking the scenario and selecting the ‘Generate Step Definitions‘ option. This is shown in in Figure C.
Figure D shows the window that the programmer sees after choosing the ‘Generate Step Definitions‘ option. The checkboxes highlight the code that will be generated in the new class that contains the definition of the steps for this particular scenario.
Let us quickly recap what we have done so far:
- We created a feature file which contains the feature and the scenarios. This is something that all stakeholders would be talking about and agreeing on during the ongoing conversations.
- We created step definitions for each step in the scenario (a step is anything that starts with Given, And, When, Then).
These files will now appear in the project as shown in Figure E.
Figure F shows the code that is generated as a result. The method names correspond to the names of the steps. This is one of the important things Dan North recommended in his ‘Introduction to BDD’ article.
He reasons when developers use sentences for test method names “…they found that when they wrote the method name in the language of the business domain, the generated documents made sense to business users, analysts, and testers.” This goes back to the main focus of BDD, which is to improve communication amongst stakeholders. It also makes ‘generated documents’ such as API documentation easy to read.
We can now run these tests. This is done by right-clicking the feature file and selecting ‘Run SpecFlow Scenarios‘ option for the list
Figure H shows the result. The test is completely skipped at this stage because nothing has yet been implemented as described in Figure F above.
We will implement the step definitions of the ‘New member name is not blank‘ scenario.
Now our goal is to implement some code to make our test pass. We will create an object of the CodingClub class, which is part of the main Coding Club application and call methods on it.
The new code is listed in Figure I. The code should be self-explanatory and the various parts are explained with comments. It is important to note that in the Given step definition, (.*) is entered in the annotation. That is what picks up the parameter (string name) when the code inside it is executed.
We will now re-run the test. This time the test not skipped. It runs and passes (see Figure J).
Multiple Scenarios using the same Step Definitions
In the previous example, we:
- Wrote a scenario
- Added step definitions for it
- Implemented the steps
- Executed the tests
In the real world, we are likely to have several scenarios for a feature. But does this mean we will need to generate step definitions for each scenario separately? Surely, that makes BDD a lot more tedious. Is there a way to execute multiple scenarios using the same step?
The good news is that, yes, there is. We will now take the previous example further to include a second scenario. The scenarios we will use are shown in Figure K.
The second scenario executes a test when the field value is blank. In order to enable us both scenarios using the same steps, we will put valid and invalid in quotes so we can pass them as parameters in the step definition. We will also have another parameter for the empty value and call it ‘nothing’.
Just as we did in the previous example, we will generate the step definitions and then implement them (see Figure L and Figure M).
For the Given step definition, we have added some code to check for the value ‘nothing’ in the parameter, and then replace it with an empty string. We do this so we can test the scenario where the member name field is blank (see Figure L).
Figure M shows how we have tweaked the Then step definition to include a parameter (where the value can be ‘valid’ or ‘invalid’ depending on which scenario is being executed). Based on the value of the parameter, we will either test the scenario where the member name is not blank or where the member name is blank.
We will now run and both scenarios again. The result is shown in Figure N, where both tests have passed.
In this article, we first used a simple example of a scenario and implemented the step definitions to demonstrate the practical implementation of the ideas that were described in the previous article. We then took it further and added a second scenario to demonstrate how it is possible to run multiple scenarios using the same step definitions.
It is clear that the approach we described shares some similarities with Test Driven Development. We wrote a test, saw the Test Explorer skip the test when it wasn’t implemented and then we added some code to make ensure the test passed. The main difference here is the fact that the requirements which were agreed on during requirements analysis were made executable, and later can be used as Acceptance Criteria during UAT.
However, what evidence can we show to prove that BDD methodology is as efficient as we think it is? This question will be answered in the next article where we will explore how the executable criteria helps improve the quality of the software application and does so in the least time-consuming manner.