# SpecFlow: simplifying ATDD and BDD

Tags: , , , , | Categories: .NET Posted by oleksii on 3/23/2011 8:19 PM | Comments (0)

I have been working on some acceptance tests and found a valuable tool — SpecFlow. Nowadays, testing with SpecFlow/Cucumber or similar tools seems to gain speed, with more and more people consider utilising power of ATDD and BDD. Essentially, SpecFlow makes it possible for business people to define valuable behaviour for the project.

I have adapted code defined in Oren’s blog to show the simplicity of SF. In the post Oren presented new syntax for unit testing namely Arrange-Act-Assert. The types under test are defined as

public interface IUserRepository{    User GetUserById(int id);}public interface INotificationSender{    void Send(string message);}public class User{    public int Id { get; set; }    public string Name { get; set; }}public class LoginController{    private readonly IUserRepository repository;    private readonly INotificationSender sender;    public LoginController(IUserRepository repository, INotificationSender sender)    {        this.repository = repository;        this.sender = sender;    }    public void ForgotMyPassword(int userId)    {        User user = repository.GetUserById(userId);        sender.Send("Changed password for " + user.Name);    }}

And the test looks like this:

[Test]public void WhenUserForgetPasswordWillSendNotification_UsingExpect(){    var userRepository = MockRepository                                .GenerateStub<IUserRepository>();    var notificationSender = MockRepository                                .GenerateMock<INotificationSender>();    userRepository.Stub(x => x.GetUserById(5))                    .Return(new User { Id = 5, Name = "ayende" });    notificationSender.Expect(x => x.Send(null))                    .Constraints(Text.StartsWith("Changed"));    new LoginController(userRepository, notificationSender)                    .ForgotMyPassword(5);    notificationSender.VerifyAllExpectations();}

Well, if I didn’t happen to know the programming language, I would immediately fail to understand what is happening. Let’s see how I can rewrite the test in a more domain-oriented and business-friendly way.

Firstly, using NuGet I install the following tools

PM> install-package SpecFlowPM> install-package RhinoMocks

Secondly, I define a test from a business perspective. Tests are written in a Gherkin language.

Feature: Send Notification    In order to automate support services    And solve trivial problems quickly                               As a company with high standard of support    We want to send emails@sendNotificationScenario: Send forgot password notification    Given user forgot password           When he clicks on a forgot password link    Then new password is sent

Now, as a developer I generate  a “code behind” and insert it into the send notification feature steps

[Binding]public class SendNotificationSteps{    private IUserRepository userRepository;    private INotificationSender notificationSender;    [BeforeScenario]    public void Initialize()    {        userRepository = MockRepository.GenerateStub<IUserRepository>();        notificationSender = MockRepository.GenerateMock<INotificationSender>();    }    [Given(@"user forgot password")]    public void GivenUserForgotPassword()    {        userRepository.Stub(x => x.GetUserById(5))                                .Return(new User { Id = 5, Name = "ayende" });        notificationSender.Expect(x => x.Send(null))                                .Constraints(Text.StartsWith("Changed"));    }    [When(@"he clicked on a forgot password link")]    public void WhenHeClickedOnAForgotPasswordLink()    {        new LoginController(userRepository, notificationSender).ForgotMyPassword(5);    }    [Then(@"password changed notification is sent")]    public void ThenPasswordChangedNotificationIsSent()    {        notificationSender.VerifyAllExpectations();    }}

So without altering Oren’s test (just rearranging), this is what I can get as the output

Conclussions:
SpecFlow allows non-technical folks to define features and correspondent tests. Each line of scenario corresponds to a method, where a technical dude writes code. Features are defined in a meta language Gherkin that can be learned within five minutes. SpecFlow supports NUnit, MSTest, MbUnit and any mocking framework. What I noticed so far it is a little bit tedious to configure tests on a build machine and as it is a fresh tool occasional error do occur (however they are not brain teasers and can be quickly fixed).

If you enjoyed this post, make sure you subscribe to my RSS feed!

# The difference between a mock and a stub

Tags: , , , | Categories: .NET, Architecture Posted by oleksii on 2/1/2011 6:01 PM | Comments (0)

I got an interesting question today and I partly failed to answer it.

The question was: what is the difference between a mock and a stub?

Although I spent sufficient amount of time writing unit tests with and without mocking objects, I was unable to provide a clear answer. Having searched the internet afterwards, I found one of the classic article by M. Fowler that I managed to miss somehow. The article is very detailed, but long story told short:

Using stubs – is the classic TDD approach where unit tests are designed to check state. A general core workflow would be calling a method of an object/type with subsequent verification that the state has been updated.

Using mocks – is a TDD variation - BDD - that aims to track behaviour. Typical scenario would be creating a pre-programmed workflow and check if a real-world object follows the predefined behaviour.

What is better? Which path to choose? These are debatable questions and are highlighted by Martin in his article “Mocks Aren't Stubs”.

If you enjoyed this post, make sure you subscribe to my RSS feed!