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.
[TestFixture]
public class SecurityRepositoryFixture
{
private Mock<ISecurityProvider> _securityRepositoryMock;
private SecurityRepository _securityRepository;
[SetUp]
public void SetUp()
{
_securityRepositoryMock = new Mock<ISecurityProvider>();
_securityRepository = new SecurityRepository
{
SecurityProvider = _securityRepositoryMock.Object
};
}
[Test]
public void CheckRegistration_User_Is_Registred_Test()
{
Mock.Get(_securityRepository.SecurityProvider).Setup
(x => x.CheckRegistration("username", "password")).
Returns(true);
bool result = _securityRepository.CheckRegistration("username", "password");
Assert.IsTrue(result);
}
[Test]
public void CheckRegistration_User_IsNot_Registred_Test()
{
Mock.Get(_securityRepository.SecurityProvider).Setup
(x => x.CheckRegistration("username", "password")).
Returns(false);
bool result = _securityRepository.CheckRegistration("username", "password");
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:
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):
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.
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.
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>();
_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:
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: