BDD with SpecFlow

Behavior Driven Development (BDD) is about defining the system as a collection of behaviors and then let these behaviors drive rest of the development work. Building on my previous post , this post will have us dive deeper into the concepts of BDD. In order to understand BDD better and see the some of the concepts around it in real action, we will use a popular tool called SpecFlow from TeckTalk. Tools like SpecFlow facilitate communication between the business experts and the developers by allowing them to use a common platform to define executable system behaviors.

Before we jump into SpecFlow, let us get some of the terms and nomenclatures around this tool straightened. We will be using some of these terms over and over again in the course of this post. Two such very important terms are Feature and Scenario.

Feature – a logical unit of functionality which has a business value. For example, the ability to add a customer to the system is a feature, or the ability to send an email with the product catalog to a customer can also thought to be another feature. Creation of the “CUSTOMER_MASTER” table in the database in not a feature.

Scenarios – different conditions around a feature and the system’s expected behavior against these conditions. For example, if the customer is successfully added to the system, the user should be taken to customer-list page. If the customer is not successfully added then the user should remain in the same page and the reason of failure must be displayed.

In order to understand the idea of Feature and Scenario better, let us use an overly simplified feature for an example. Let us assume that we want to build a feature called “Customer Addition”. As the name suggests, we intend to develop a Feature which will allow the user to add a customer to the system. Let’s say we come up with two scenarios – First, when the user is successfully added to the system, and second when the user is not successfully added to the system.

SpecFlow uses  english-like language called Gherkin to write these Features and Scenarios. Gherkin is a DSL(Domain Specific Language) and hence can be understood by the Business folks and the SMEs quite easily. Gherkin uses .feature file to specify a Feature. The Feature keyword marks the beginning of a feature. For more details on the syntax of Feature see this link. This descriptive text in nature and is used to describe what the feature is supposed to do. It need not necessarily follow a particular convention or pattern. SpecFlow recommends using the following template though.

In order to [reason]
As a [role]
I want to [functionality]

A Feature typically consists of one or more Scenarios. The scenarios must follow the Given-When-Then syntax,

Given – precondition or the state of the System (Under Test) prior to the action
When – action taken
Then – result or the state of the System (Under Test) after the action

Okay! Back to our “Customer Addition” feature. SpecFlow installs few templates in the Visual Studio. One such template is called SpecFlow Feature File and has the .feature extension. Let us create our feature using the SpecFlow Feature File and name it CustomerAddition.feature. In light of the conventions discussed earlier in the post, the feature should look something like this,

Feature: Add a CustomerIn order to maintain the customer’s information
As the authorized user of the system
I want to add a customer to the systemScenario: Customer Added successfully
Given the following customer
|Name  |Phone  |Address    |
|Rob  |678-826-6675 |514 M cricle, Atlanta, GA 30328 |
When I click “Add”
Then go to the customer-list page and display the added customer

Scenario: Customer not Added successfully
Given the following customer
|Name  |Phone  |Address    |
|Jane|678-826-6675 |120 Park Dr, GA 30300 |
When I click “Add”
Then stay in the same page and display the error

What is actually happening here is that every time the Feature file is saved, SpecFlow parses it and generates a code-behind file for it. Under the hood, all this generated piece of code essentially does is call few methods (tests) for these Given, When and Then statements. If we go ahead and try to run our Feature file (using MSTest or NUnit) at this point, we will see that SpecFlow is complaining that it does not find a matching step definition for the Given, When or Then statements.

   
No matching step definition found for the step. Use the following code to create one:
    [Binding]
    public class StepDefinitions
    {
        [Given(@”the following customer”)]
        public void Given(Table table)
        {
            ScenarioContext.Current.Pending();
        }
    } 

Let’s go ahead and add something called the SpecFlow Step Definition file from the Visual Studio. A Step Definition File tells the runtime which method (step) should be executed for a Given or When or the Then statement. This wiring up is done by the [Binding] attribute that decorates the StepDefinition class. If our Step Definition Class were called the CustomerAdditionStep, then using the generated code in the error message we can create a class which would look like the following,

   
    [Binding]
    public class CustomerAdditionStep
    {
        [Given(@”the following customer”)]
        public void Given(Table table)
        {            
            // …..
            //Implement the tests and asserts here
         }
    }
 

We can write tests and assertions using these methods and automate a business scenario using these step definitions.

This is a very simple demonstration of how a tool (SpecFlow in this example) can be used to provide a common platform for both business and the development folks to be able to collaborate, develop a shared understanding of the system and then be able to automate that shared understanding. In other words, SpecFlow allows the devs and the BAs to collaborate and define executable behaviors for the system (in terms of scenario) and then let these set of behaviors drive the development of rest of the system.

Advertisements

Get Your TDD Right with BDD

If you have been using TDD (Test Driven Development) or even maintaining unit-tests at some level, then probably you have already been using these tests as a means to express the business requirement. Writing unit tests before writing the actual implementation code is undoubtedly a very good exercise to brainstorm and understand problem before making an attempt to solve it. But for developers who are writing these tests, there is always a chance of missing out something of business importance or misinterpreting a business requirement. In other words, though these tests might be good for many things but they hardly make any attempt to bridge the age old gap between the business needs and the code development.

Another ailing thing about TDD is the name itself. ‘Test’ driven development is hardly about testing. It has never been about doing the tester’s job. Many people would say TDD is and has always been about good design. I do not completely agree with that either. Good design is a very good by-product of TDD, but that’s not the primary purpose of TDD. The very name and the nomenclature around it, words like Test, Assertion etc, influences the brain (Sapir–Whorf hypothesis) compels it to think that TDD has got something to do with testing.

TDD also requires a fundamental shift in focus as a developer. For decades we developers have been thinking about those grand software designs up-front, creating the databases, the data-access classes, the business facades, re-usable components and what not before addressing the actual business needs in small bits. TDD done right demands for a drastic change in this mindset. It requires the developer to think about the business needs first. Pick a very tiny slice from it which still has a business value and write only as much code that is required to implement this piece of business value. Really, this might not be the most intuitive thing to do for most of the developers. Moreover, this ‘no up-front design’ idea (though I do not completely agree with it) does not work in the best interest of someone like me who sell themselves as ‘Architects’. Pun intended!

No wonder so many teams struggle to get TDD right.

Due to some of these inherent problems with TDD and the huge gray area without sufficient guidelines on what and how much to test, people like Dan North came out with the idea of BDD a.k.a. Behavior Driven Development. The idea behind BDD is pretty simple. The idea is to provide a common tool and guideline to both the business and development folks. This tool/guideline would allow the business analysts and SME’s to write the business requirements (in a specified format) using english-like language. They would write the different business scenarios around the requirement. In other word, they would define the ‘Behavior’ of the system. The same tool would be able to generate or at least guide developers write the test-cases from these scenarios. The developers would implement these test-cases one by one and make all the tests go green. And TADA! In a perfect world, you have a business requirement translated into a working code.

With BDD the point really is to be able to write tests which are more relevant. Tests which matter. Tests which are derived right out of the business requirements and scenarios, coming right out of the horses mouth. BDD is about putting some more structure and discipline into the Test Driven practices you already claim to do.