In this post, we will be discussing about BDD and its implementation with C#. This article will be divided into multiple parts. This part will be covering the introduction of BDD and its implementation with C# with a basic example.
Need Of BDD ?
Lets take an example, business comes with a requirement of customer search functionality and say Business Analysts have written the user story some what like this.
As a user I should be able to search customer details with First Name,Last Name,Flat Number and Pin Code.
User enters the following combination (First Name +Last Name),(First Name + Flat Number + Pin Code), (Last Name + Flat Number + Pin Code) exact customer details should be extracted. With Firstname, Lastname, Flat Number or Pin Code list of customers should be extracted.
Consider one scenario in BDD
When user enters the first name
and user enters the last name
Then the user should be able to see a single customer record with customer details
Did you observe the difference in readablity, it has become better isn’t it? This might be a simple scenario but in real world we have to face complex scenarios then the difference becomes more clear.
When a user with no understanding of application looks at the above scenario, it would become very easy for him to understand this.
What is BDD ?
BDD stands for Behavior driven development. It is a methodology that is followed while development of a system. Most of us relate BDD only to Automated testing and think that implementation of BDD takes only to write GIVEN WHEN and THEN, but it is more than that and on a whole it’s a methodology. As the name stands Behavior Driven Development, it makes us focus on the behavior of the module that is being developed. A particular user story is broken down from a user perspective and how user uses it and then the development kick starts. In simple words it focuses and symbolizes on WHY we are writing the code and WHAT does the code achieve in terms of functionality and how the end users get benefited. Lets see how we can achieve this.
In the upcoming posts I have planned to show a complex requirement and how it can be achieved using BDD and also on the advanced concepts of Specflow depending on availability.
Readers can understand better if they have the basic OOPS understanding and also some hands on experience with Visual studio.
How can we implement BDD
I have personally seen many projects where the thoughts of implementing BDD kick starts and gets blocked in implementation. Reasons might be many lets not dig into it, let us focus on what it takes to implement BDD. Let us start with the initial meet where Product Owner or the Business comes up with certain requirements and the discussion happens between BAs and POs. When the user stories are clear to BAs and they come up to team to discuss about the same, here comes the concept of BDD. Where the whole team sits together to break the user story into user behavior and convert these user behavior into scenarios which can be easily understood for a normal user who doesn’t have functional understanding. These scenarios should exactly replicate user behavior.
Pre-requisites for implementing BDD with C#
Note – This article is mainly focused from a C# development perspective.
Visual studio provides an extension called Specflow, this helps us to write the scenarios in Gherkin language which is plain English text. Add Specflow to project
BDD Work flow :
Starts with Feature File where we can write down the scenarios in Given When and Then.
When we add this extension to project we would be getting feature, stepdefinition etc templates for implementing BDD. As we can see in the below screenshot, we have feature file and stepdefinition templates and the extension for feature.
After adding the feature lets see how the template looks:
It starts with Feature tag, this is the place where we define what is the exact functionality that this feature would achieve.
Then comes the Scenario, this is where we write a group of statements which produces some kind of output that is expected. As we can see here the scenario is written in Give When and Then. These 3 keywords are recognized by Specflow. Don’t get confused with AND keyword here as it replicates the GIVEN before it. If there are multiple Given When and Then we can simply put AND after first Given When and Then. Each statement or Each Given Then or When that we write is called a step and it is associated to code via step definition which we will be discussing next.
Like this we can write down multiple scenarios and each scenario should replicate the user behavior. Keep an eye on the color of the steps. Right now these are pink, when we associate it to their particular step the color changes. This is a great advantage we have using Visual studio, since the feature when compiled doesn’t give a compile time error if a step is not associated with any step definition the only way to find out an unused step is through color.
When we save the feature file, there is a feature.cs file which is auto generated. Best practice is not to add or change the feature.cs file manually as it is auto generated and may lead to compile time errors and always save the feature file before committing or else the changes would not be reflected in .cs file. The .cs file has the information about scenarios, Specflow version used test runner information etc.
Here comes the beauty of this extension and also the concept of how every step that we write is associated to code. When you look into the definition of the step in feature, we will see a pop up coming up. Let us do it for the first step as shown below.
Copy this to clip board, and add a step definition file to the project. Naming convention that is followed while naming this file is FeatureName+Steps.cs. We have addition feature, so this would be AdditionSteps.cs. This helps in better readability and also if we are having a big set of stepdefinition files, we can easily differentiate what we are looking for. Again don’t forget that we are implementing BDD, so we have to be particular on naming and every file should symbolize the functionality that it achieves.
When we add we can see the default template that would be associated to the default feature template of addition of two numbers. Adding the screenshot of feature too so that it would be easy to relate. As discussed above, the color of the steps if associated to step definition must change. Lets see it
Before adding step definition
Add step definition file
After adding step definition file. still we can see one step in pink the reason being that we added it manually in addition to the default template provided. So just go into definition and then copy the code and paste it in step definition.
Now we can see each and every step is bound to a step definition.
Lets start with Binding attribute that is in class. This attribute links the feature to step definition. So when the code runs, it would search for all the class files which has Binding attribute and then the particular step. As we can see each method is attributed with the exact step that we have in feature. This is important to note, you might miss on this while writing features so please make sure you either copy the auto code and paste it here or write it manually with more attention as you will not get any compile time error when the step doesn’t have a matching step definition, it would fail at run time and you might spend hours to realize what went wrong.
Now let us come to implementation that is shown in each method. The standard line ScenarioContext.Current.Pending() states that the current context of the scenario is pending implementation. Pay attention on ScenarioContext class as it is most important as we progress. Let us write some simple code and make this test pass.
As you can see, scenario context is a kind of storage till the scenario execution is in scope. You might think of how the step that we have written has a input parameter in the step definition. Every step that we write each is by default read as string. If we have anything other than string in this case an int, we get it as parameter to our method. You can add a reference to your library and invoke the method under test from anywhere in the stepdefinition as per your need. Finally we assert the expected and actual result from our logic.
Use MSTest as default test runner and check the app config if it’s the same there too. You can right any kind of logic in step definitions file and see that the step definition file is not overloaded with lot of service calls or business logic code. Practice suggests the step definition files to be static as they can be used across the scenarios and should only contain the logic to handle input and assert output in addition to other class calls. Achieve this by adding some common helper classes which perform or call the classes that contain all the required business logic.
This was an introduction to BDD and I hope you get some insight into it as it is a beautiful way to implement functionality. In the upcoming post I would like to go with a complex example and see how we can achieve it.