There is no silver bullet

Aaah - back from the post-technical

How not to use Cucumber

Business Facing?

I’ve seen some horrible Cucumber scenarios in recent years. Some of the worst examples look like this (except much worse).

Scenario: Sucessful user registration
When I go to the user registration page
And I fill in “user_name” with “Joe Bloggs”
And I fill in “user_email” with “joe@bloggs.com
And I fill in “user_phone” with “+44 4444 4441”
And I click “#commit”
Then I should see “You have signed up successfully”

Notice the element ids in here – this is not uncommon.

Even your testers will have little interest in scenarios written like this, if you show them to a BA, or even worse one of the project’s stakeholders, they will think you are mad.

Why would they be interested in a test? Why would they be interested in such a trivial feature?

Does this scenario even need to exist?

What you are showing them is a test, and BDD is not about testing.

These kind of Scenarios tend to come from developers who have previously been working with something like Selenium. In fact I’ve seen some scenarios that are quite literally a direct translation of an existing Selenium test, 100 steps long and completely unreadable to anyone. No-one has ever even asked the question ‘what are we trying to test here?’. Nobody knows if it tests what it’s supposed to test because no-one understands it.

The first thing to look at when faced with a “Scenario” like the one above is whether it needs to exist at all. This is the subject of another post so for the moment lets assume it does.

How can we improve on this?

In a word, refactoring. A lot of developers seem to forget that by the time you come to implement them, these scenarios, and the steps that support them, are code. We wouldn’t accept unreadable code (actually from bitter experience there are plenty who will), so why accept it in automated examples?

So how would we get started refactoring the example above?

The most obvious thing is the amount of duplication in “When I fill in..”

Filling in a form is common enough to warrant a step of it’s own, so we could (I’m not saying we should) implement something like:

When(/^I fill in the form with the following details$/) do |table|
table.hashes.first.each do |key, value|
fill_in(key, with: value, exact: true)
end
end

A step like this would allow you to change you scenario to:

Scenario: Sucessful user registration
When I go to the user registration page
And I fill the form with the following details
| Name | Email | Phone |
| Joe Bloggs | joe@bloggs.com | +44 4444 4441 |
And I click “Sign Up”
Then I should see “You have signed up successfully”

It’s better, and using the correct text in the table header (label text not tag’s id) has the side effect of making sure your labels are correct. But it’s still not domain language. Wouldn’t it be better if we could write it as

Scenario: Sucessful user registration
When I register with the following details
| Name | Email | Phone |
| Joe Bloggs | joe@bloggs.com | +44 4444 4441 |
Then I should see “You have signed up successfully”

or even

Scenario: Sucessful user registration
Then I should be able to register successfully with the following details
| Name | Email | Phone |
| Joe Bloggs | joe@bloggs.com | +44 4444 4441 |

Which of these you implement is up to the 3 amigos. Choose the language which best reflects your shared understanding of the domain.

I realise this is a very trivial example, but you should be able to get the idea from it. The scenarios should be used mainly as a way to talk about the requirements with the people who care.

As a side effect, the resulting scenarios will be less brittle. Any change to the registration process will only affect the step unless there is a need to capture more data. In this case just adding a column to the table in the .feature file should cover that if it’s relevant in a particular scenario.

Your stakeholders will thank you for it (eventually).