Are BDD tests acceptance tests?

Viewed 12849

Do you need something like Fitnesse, if you have BDD tests?

7 Answers

I don't know if there's such a thing, strictly speaking, as a "BDD test". BDD is a philosophy that suggests how you can best interact and collaborate with stakeholders to complete a complex project. It doesn't directly make any prescriptions for the best way to write tests. In other words, you'll probably still have all the usual kinds of tests (including acceptance tests) under a BDD-philosophy project.

When you hear of "BDD frameworks", the speaker usually means a framework for writing all your usual kinds of tests but with a BDD twist. For example, in RSpec, you still write unit tests; you just add the BDD flavor to them.

While BDD is larger than the scope of just tests, there are indeed BDD tests. These tests are Unit Tests that follow the BDD language.

Given some initial context (the givens), When an event occurs, then ensure some outcomes.

There are a few good BDD frameworks available depending on your language of preference. JBehave for Java RSpec for Ruby NBehave for .NET

I like to draw a distinction between "specs" and "tests."

If I am covering a method called GetAverage(IEnumerable<int> numbers), I am going to write a more or less standard unit test.

If I am covering a method called CalculateSalesTax(decimal amount, State state, Municipality municipality), I am still going to write the unit test, but I'll call it a specification because I'm going to change it up (1) to verify the behaviour of the routine, and (2) because the test itself will document both the routine and its acceptance criteria.

Consider:

[TestFixture]
public class When_told_to_calculate_sales_tax_for_a_given_state_and_municipality() // the name defines the context
{
    // set up mocks and expected behaviour
    StateSalesTaxWebService stateService 
        = the_dependency<IStateSalesTaxWebService>;
    MunicipalSurchargesWebService municipalService 
        = the_dependency<IMunicipalSurchargesWebService>;

   stateService.Stub(x => x.GetTaxRate(State.Florida))
        .Return(0.6);
    municipalService.Stub(x => x.GetSurchargeRate(Municipality.OrangeCounty))
        .Return(0.05);

    // run what's being tested
    decimal result = new SalesTaxCalculator().CalculateSalesTax
        (10m, State.Florida, Municipality.OrangeCounty);

    // verify the expected behaviour (these are the specifications)
    [Test]
    public void should_check_the_state_sales_tax_rate()
    {
        stateService.was_told_to(x => x.GetTaxRate(State.Florida)); // extension methods wrap assertions
    }

    [Test]
    public void should_check_the_municipal_surcharge_rate()
    {
        municipalService.was_told_to(x => x.GetSurchargeRate(Municipality.OrangeCounty));
    }

    [Test]
    public void should_return_the_correct_sales_tax_amount()
    {
        result.should_be_equal_to(10.65m);
    }
}
Related