Click here to Skip to main content
15,861,172 members
Articles / Programming Languages / C#

Introduction to BDD using StoryQ

Rate me:
Please Sign up or sign in to vote.
4.50/5 (8 votes)
10 Jun 2010CPOL3 min read 32.7K   165   25   4
Getting started with BDD in an easy way

Introduction

TDD is without doubt an effective approach to produce "safe" code. In this case, with "safe" we mean code that has been tested more than extensively, bulletproof code in few words.

What TDD misses is the chance of grouping and gives a sense to the several tests (perhaps hundreds, thousands?) we got in our projects. The only tip we got is the description in the method name.

Here is where BDD comes in help, making our tests much more descriptive and logically grouped.

Background

A background on Test Driven Development is a good start to understand what BDD is all about. The Art Of Unit Testing from Roy Osherove is one of the best books out there on the argument: give it a check, it's worth it. In the meanwhile, a quick search on the web will give enough information to get started.

What's BDD?

BDD stands for Behavior Driven Development, Wikipedia defines it as " an agile software development technique that encourages collaboration between developers, QA and non-technical or business participants in a software project", I prefer Jeremy Miller's definition where: "BDD is an evolution of TDD with a better syntax and mechanics for expressing the desired functionality with tests/specifications". Nothing revolutionary, nothing completely new but an improvement of what we already got.

Let's go further.

Traditional TDD Test

TDD fans will easily recognize the code below as a traditional Fixture: there's the Setup where we initialize (and mock) the classes under test and the test methods containing the AAA syntax.

C#
[TestFixture]
    public class SecurityRepositoryFixture
    {
        private Mock<ISecurityProvider> _securityRepositoryMock;
        private SecurityRepository _securityRepository;


        [SetUp]
        public void SetUp()
        {
            _securityRepositoryMock = new Mock<ISecurityProvider>();
            //mocking the security provider
            _securityRepository = new SecurityRepository
                        {
                             SecurityProvider = _securityRepositoryMock.Object
                        };
        }

        [Test]
        public void CheckRegistration_User_Is_Registred_Test()
        {
            //Arrange
            Mock.Get(_securityRepository.SecurityProvider).Setup
		(x => x.CheckRegistration("username", "password")).
                Returns(true);
            //Act
            bool result = _securityRepository.CheckRegistration("username", "password");
            //Assert
            Assert.IsTrue(result);
        }

        [Test]
        public void CheckRegistration_User_IsNot_Registred_Test()
        {
            //Arrange
            Mock.Get(_securityRepository.SecurityProvider).Setup
		(x => x.CheckRegistration("username", "password")).
                Returns(false);
            //Act
            bool result = _securityRepository.CheckRegistration("username", "password");
            //Assert
            Assert.IsFalse(result);
        }
    }

The tests covers two cases: one where the check fails and one where the check succeeds. The output we will get is:

tddscreen.JPG

What's New with BDD

Before diving into the code, let's do a quick excursion on what a BDD test is made of:

A BDD test is mainly composed by a descriptive part that doesn't rely in any way with the code you execute. This part is commonly called Feature, and it will be what the business will give you to develop around, it is the case scenario.

Here's our case scenario (a.k.a. story):

storyscreen.JPG

As you can see, it is a human readable requirement. To do BDD, I am using a framework named StoryQ.

StoryQ comes with a WPF client able to convert your plain text specifications into a BDD test.

storyqclient.JPG - Click to enlarge image

A BDD test is composed by its specification plus links to one or more methods witch executes the "real" test (setting up the objects, calling the method to test, evaluating the asserts). To be recognized as a valid story, our specification must use Gherkin keywords.

Below is the BDD version of the same tests. The method containing the story will be the test method, the story in StoryQ ends with .WithScenario. What's after is the sequence of the methods to be executed.

C#
public class SecurityRepositoryStories
   {
       private Mock<ISecurityProvider> _securityRepositoryMock;
       private SecurityRepository _securityRepository;
       private bool _result;

       [Test]
       public void CheckRegistration_User_Is_Registred_Test()
       {
           new Story("User registration")
               .InOrderTo("Check if an user is granted to access a resource")
               .AsA("user")
               .IWant("a user to be granted if the username/password pair is correct")
               .WithScenario("Correct credentials")
               .Given(SetupRepository)
               .When(CheckRegistration, "username", "password", true)
               .Then(Verify, true)
               .Execute();
       }

       [Test]
       public void CheckRegistration_User_IsNot_Registred_Test()
       {
           new Story("User registration")
               .InOrderTo("Check if an user is granted to access a resource")
               .AsA("user")
               .IWant("a user to be granted if the username/password pair is correct")
               .WithScenario("Incorrect credentials")
               .Given(SetupRepository)
               .When(CheckRegistration, "wrongusername", "wrongpassword", false)
               .Then(Verify, false)
               .Execute();
       }

       private void SetupRepository()
       {
           _securityRepositoryMock = new Mock<ISecurityProvider>();
           //mocking the security provider
           _securityRepository = new SecurityRepository
                       {
                            SecurityProvider = _securityRepositoryMock.Object
                       };
       }

       private void CheckRegistration
       (string username, string password, bool mockRetValue)
       {
           Mock.Get(_securityRepository.SecurityProvider).Setup
       (x => x.CheckRegistration("username", "password")).
               Returns(mockRetValue);
           _result = _securityRepository.CheckRegistration(username, password);
       }

       private void Verify(bool expected)
       {
           Assert.AreEqual(_result, expected);
       }
   }

The value of BDD is clearly in the output that is fully self describing:

bddoutput.JPG

Points of Interest

This article doesn't pretend to be a deep dive in Behaviour Driven Development, but only a quick start to get the basic concepts of this cool technique to write tests in your projects.

BDD allows you having tests ordered and grouped with a logic (not unpacked ones as in TDD) and to produce logs and outputs that can be handled also by non technical persons.

References

There are quite a lot of frameworks to do BDD, I personally like StoryQ but excellent alternatives can be:

If you want to know more about BDD, here are some useful links:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Minalabs
United Kingdom United Kingdom
Giorgio Minardi is a .Net consultant actually working in UK after diffent years spent in Italy working on enteprise clients.

Comments and Discussions

 
Questionnice Pin
BillW3330-May-13 7:25
professionalBillW3330-May-13 7:25 
GeneralMy vote of 5 Pin
Kanasz Robert28-Sep-12 5:54
professionalKanasz Robert28-Sep-12 5:54 
GeneralMy vote of 3 Pin
Mat Kramer27-Aug-11 17:27
Mat Kramer27-Aug-11 17:27 
GeneralMy vote of 5 Pin
Robert_Dyball10-Feb-11 16:27
professionalRobert_Dyball10-Feb-11 16:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.