BDD (Behavior Driven Development)
 

In the previous article we looked at how to do Test Driven Development (TDD) while doing the XP (Extreme Programming). In XP, the implementation of the tasks are done in the steering phase of the iteration planning. One of the tenets of the steering phase is “functional tests are run”. In this article we will see how to create functional tests using Behavior driven development (BDD) and its benefits.

Following are the some of the benefits of automated functional tests.

  • Functionality experienced by the User is tested
  • Saves testing time for the developers
  • Test in every environment (Dev, QA, Stage) without much effort
  • Generates confidence in every stake holder

Tools required for doing BDD in .Net

There are various tools available to do BDD in .Net. I have listed few of them below

SpecFlow is one of the most popular tools used in the .Net/C# community. And in this blog lets use the same. The tool comes as a Visual Studio Extension and can be downloaded directly from VS.

Creating a SpecFlow Project

Once SpecFlow extension is installed, the template required for doing BDD will be installed.

  • Create a simple “Class Library” Project in Visual studio
  • In the project, create a SpecFlow Feature file

Selecting the test framework

Before we Create/execute the scenario, we need to wire the SpecFlow with a compatible test framework. To do that we need to make changes to the app.Config file of the project.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow" />
  </configSections>
  <specFlow>
    <!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config -->
  <!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config -->
    <unitTestProvider name="xUnit" />
  </specFlow>
</configuration>

In this example we are using XUnit as the testing framework. SpecFlow supports a series of testing frameworks and more details can be found here.

Creating the Behavior

Now, let us look at how to create a functional test using behavior driven approach. Let’s consider the following story while creating a POS (point of sale) application for a super market.

“As a Supermarket POS app developer,  i would like the API to Give the total amount while billing so that I can wire up API against the UI.

Let’s write the Behavior required in order to implement the above API requirement .

Feature: SuperMarketProductsAPI
	As a Supermarket Biller 
	i would like the API to
	Give the total amount while billing
@SmokeTest
Scenario: Find the total amount while billing
	Given Shopping cart is filled with all the items required by consumer
	And Campaign information for the month is available in the system
	When I pass the cart to create bill API
	Then the total bill amount should be calculated

The above specification is written using the custom language (testing DSL) create by the specflow.org. (Please read about what is DSL here.)

There are 2 parts to the above Specflow specification

  • Feature – Denotes bigger context (description/story) of the application
  • Scenario – Specific workflow or behavior of the system under the feature. Each scenario has the following sub-parts
    • Given, And – describes what we already assumed available
    • When – The specific action which will trigger the workflow/behavior
    • Then  – expected behavior

 

Creating step definitions

When we run the unit test corresponding to the above test we it will fail as there are no definitions corresponding to the above scenarios.

Now Right Click on the feature file and select “Generate step Definitions”

You will see the pop-up like below, select “Generate” and then “Save” the file.

The file will have the details about “what SpecFlow should do when test is executed”.

using System;
using TechTalk.SpecFlow;

namespace SuperMarketFunctionalTests
{
    [Binding]
    public class SuperMarketProductsAPISteps
    {
        [Given(@"Shopping cart is filled with all the items required by consumer")]
        public void GivenShoppingCartIsFilledWithAllTheItemsRequiredByConsumer()
        {
            ScenarioContext.Current.Pending();
        }
        
        [Given(@"Campaign information for the month is available in the system")]
        public void GivenCampaignInformationForTheMonthIsAvailableInTheSystem()
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"I pass the cart to create bill API")]
        public void WhenIPassTheCartToCreateBillAPI()
        {
            ScenarioContext.Current.Pending();
        }
        
        [Then(@"the total bill amount should be calculated")]
        public void ThenTheTotalBillAmountShouldBeCalculated()
        {
            ScenarioContext.Current.Pending();
        }
    }
}

When you build the project and execute the test corresponding to this, it will fail. This is because none of the parts of the test (given, when, then) are having implementation.

Writing code to make it work

Now that the behavior has been created, we are good to validate that with the team and implement the code/functionality corresponding to the requirement. Of course using best coding practices like TDD 🙂

Making the behavior test pass

In order to make the behavior test pass we need to write the implementation in the “Step Definition” file.

namespace SuperMarketFunctionalTests
{
    using Newtonsoft.Json;
    using System.Collections.Generic;
    using System.Net.Http;
    using TechTalk.SpecFlow;
    using Xunit;

    [Binding]
    public class SuperMarketProductsAPISteps
    {
        Product P1 = new Product { Name = "test1", Cost = 5 };
        Product P2 = new Product { Name = "test2", Cost = 10 };
        ShoppingCart cart;
        List<Campaign> campaign;
        Bill bill;
        [Given(@"Shopping cart is filled with all the items required by consumer")]
        public void GivenShoppingCartIsFilledWithAllTheItemsRequiredByConsumer()
        {
            cart = new ShoppingCart { Products = new List<Product> { P1, P2 } };
        }
        
        [Given(@"Campaign information for the month is available in the system")]
        public void GivenCampaignInformationForTheMonthIsAvailableInTheSystem()
        {
            campaign = new List<Campaign> { new Campaign { product = P1, discount = 1 } };
        }
        
        [When(@"I pass the cart to create bill API")]
        public void WhenIPassTheCartToCreateBillAPI()
        {
            var client = new HttpClient();
            var response = client.PostAsync("http://myapi.supermarket.com", new StringContent(JsonConvert.SerializeObject(cart))).Result;
            var output = response.Content.ReadAsStringAsync().Result;
            bill = JsonConvert.DeserializeObject<Bill>(output);
        }
        
        [Then(@"the total bill amount should be calculated")]
        public void ThenTheTotalBillAmountShouldBeCalculated()
        {
            Assert.True(bill.totalAmount == 14);
        }
    }
}

Once the code is there we can see the behavior test pass.

Conclusion

BDD is very powerful way of ensuring high code quality in conjunction with business requirement. In Extreme programming (XP) , BDD is considered to be a very important practice where functional tests are mandated to run at least once during the iteration.  Is BDD/Functional tests helping your team/business in achieving success or not ? Do let us know your thoughts.

TDD (Test Driven development)
 

There are lots of practices that need to be followed while doing XP as an agile methodology. And one of them is automated testing. However, there is lots of confusion in the tech industry if you want to test the behavior of the system or the subunits/parts of the system. First, lets us understand these terminologies. In this post, we will talk about Test driven development.

TDD (Test Driven development)

TDD or Test Driven development is an approach in which unit tests drive the development of the code. That is, when there is a new feature that needs to be developed, the unit tests corresponding to the feature is developed first before the actual code need to create the feature is coded.

Let’s take an example. Let’s say at a point of sale system, we need to calculate the bill based on the list of products picked by the consumer. Let’s write unit test corresponding to this code. (I have used C# based XUnit as the unit testing framework)

        [Fact(DisplayName = "SimpleBiller Should Calculate Total bill Amount")]
        public void SimpleBillShouldCalculate()
        {
            //Given
            var ProductsList = new List();
            ProductsList.Add(new Product { Name = "test Product1", Price = 5 });
            ProductsList.Add(new Product { Name = "test Product2", Price = 5 });
            var simpleBill = new SimpleBiller();

            //When
            var bill = simpleBill.GenerateBill(ProductsList);

            //then
            Assert.Equal(10, bill.TotalCost);
        }

In the above Unit test, we have 3 parts.

  • Given
  • When
  • Then

Given

This is the known part of the problem. i.e in mathematical terms, it’s part of the problem. In the example, we have initialized the variables and known things corresponding to the products (selected by the consumer) and the Biller object.

When

This is the business action based on which we are writing the code. In this case its GenerateBill action/method.

Then

The purpose of the tests is to ensure that the code/action does it properly as per the plan. In order to do that, we are asserting the assumptions/result of the method we are testing. In our case, we are asserting the total amount that the bill will have to be generated for.

Running the test

There are three stages of running the test.

  • Red – When we run the test now, it will fail as there is no code corresponding to the calculate bill functionality.
  • Green – In order to fix the above test, let’s write the real code corresponding to the above unit test/requirement.
        public Bill GenerateBill(IEnumerable products)
        {
            var bill = new Bill { Products = products };
            foreach (var product in bill.Products)
            {
                bill.TotalCost += product.Price;
            }

            return bill;
        }

Now, when we call GenerateBill method from the test, it will return the Bill with the total amount.

  • Refactor – With the above code written corresponding to the test, we are sure the functionality is correct as per the requirement. But the code is not optimal, as the foreach loop can be reduced to a simple C# LINQ  expression.
        public Bill GenerateBill(IEnumerable products)
        {
            var bill = new Bill { Products = products };
            bill.TotalCost = bill.Products.Sum(x => x.Price);
            return bill;
        }

Conclusion

TDD is a foolproof approach to developing software as per the requirement. The test also provides confidence to the developers on the edge conditions and other possibilities in the code. However, there is an alternative thought that TDD could waste developer time. Do you think, TDD is the right approach to software development? Please provide your comments.