views:

16

answers:

1

When you write Given When Then specs, do you prefer to list elements in a set in 1 When statement, or do a separate spec for each?

i.e.

GIVEN a book 
WHEN category is "Fanatsy", "Sci-Fi", or "Horror" 
THEN Buy it. 

vs.

GIVEN a book
WHEN category is "Fanatsy"
THEN Buy it.
GIVEN a book 
WHEN category is "Sci-Fi"
THEN Buy it.
GIVEN a book 
WHEN category is "Horror" 
THEN Buy it.

Further, what do you do with the rest of the set? Do you write a spec for each category that is not in your Buy-On-Sight subset to ensure it doesn't buy it?

+1  A: 

It's best if you can separate them, because that makes it easier to determine which one fails. For example if your test fails to buy "Sci-Fi" but succeeds on "Fantasy" and "Horror" how would you know which one failed? The hard part is coaxing your language into allowing you to do this without repeating yourself over and over.

That isn't as problematic on one-dimensional problems as it is on multi-dimensional problems, for example:

GIVEN a bookstore
THAT has "Fantasy", "Sci-Fi", and "Horror" books
WHEN you only have enough money to buy one book
THEN buy "Fantasy"

and

GIVEN a bookstore
THAT has "Fantasy", "Sci-Fi", and "Horror" books
WHEN you have enough money to buy two books
THEN buy "Fantasy" and "Sci-Fi"

and

GIVEN a bookstore
THAT has "Fantasy", "Sci-Fi", and "Horror" books
WHEN you have enough money to buy two books
AND you already own a "Fantasy" book
THEN buy "Sci-Fi" and "Horror"

My vote in these situations is still that you break it up as such:

GIVEN a bookstore
THAT has "Fantasy", "Sci-Fi", and "Horror" books
WHEN you have enough money to buy two books
AND you already own a "Fantasy" book
THEN buy "Sci-Fi"
THEN buy "Horror"

Meaning that you have two specs in the above case. In static languages, like C# and Java, though, I haven't found a very good way to do this. One thing that helps is to break up your arrange and assert code into reusable methods, and pick from them like you would dishes from a cafeteria line:

public virtual void Establish_context()
{
    Given_a_bookstore_that_has_Fantasy_Sci_fi_and_Horror_books();
    When_you_have_enough_money_to_buy_two_books();
    And_you_already_own_a_fantasy_book();
}

[Specification]
public void Then_buy_Sci_fi()
{
}

[Specification]
public void Then_buy_Horror()
{
}

Now you can create multiple subclasses that mixes and matches your Given and When. It reduces the pain, but still highlights the shortcoming of statically typed languages when it comes to writing really fluent BDD style code.

Michael Meadows