Tag Archives: Cucumber

Segue Steps

Sometimes customer scenarios using Gherkin (Cucumber, SpecFlow etc.) can be harder to read than necessary. Once there’s more than one “And” line in a row, I find that there’s more clutter than I’d like and it doesn’t flow as well when I read it. Let’s take this example scenario of upgrading a fremium service.

Scenario: Upgrade my SomeService subscription from Basic to Pro.
Given I am on the Basic plan
When I upgrade to the Pro plan
Then I see a message confirming the upgrade
And I see that I am now on the Pro plan
And I receive a personal thank you by email
And SomeService keeps a record of when the upgrade happened
And SomeService keeps a record of payment

There’s a feature I rarely see used, the ability to use bullets (with asterisks ‘*’). I’ve found that using this among steps with Given/When/Then can remove some of the clutter, making the scenario easier on the eye…

Scenario: Upgrade my SomeService subscription from Basic to Pro.
Given I am on the Basic plan
When I upgrade to the Pro plan
Then I see a message confirming the upgrade, and:
* I see that I am now on the Pro plan
* I receive a personal thank you by email
* SomeService keeps a record of when the upgrade happened
* SomeService keeps a record of payment

What I don’t like about this, however, is how the ‘Then’ step appears in a different context to the bullets and seems less important. To make sure that all the steps are seen as equally important, I can do this:

Scenario: Upgrade my SomeService subscription from Basic to Pro.
Given I am on the Basic plan
When I upgrade to the Pro plan
Then the following occurs:
* I see a message confirming the upgrade
* I see that I am now on the Pro plan
* I receive a personal thank you by email
* SomeService keeps a record of when the upgrade happened
* SomeService keeps a record of payment

Note how I’ve put in a “Then” step that segues from the “When” to the actual expectations.
A ‘Segue Step’ doesn’t have to do anything, other than transition the reader from the previous steps to a list of expectations:

Then /^the following occurs:$/ do #nothing
#just segue to the next step
end

Another way of using a Segue Step could be like this:

Then I should:
* See a message confirming the upgrade
* See that I am now on the Pro plan
* Receive a personal thank you by email
And SomeService should:
* Keep a record of when the upgrade happened
* Keep a record of payment

Asterisks can replace the opening keyword of any type of step, but using them in this way for Given or When steps could be a scenario-smell, suggesting that the scenario has too much detail or those steps are at the wrong level of abstraction. Using asterisks and Segue Steps are most appropriate in “Then” statements with two or more “And” lines.

After doing this, reading scenarios without asterisks and ‘Segue Steps’ now feels like the “And Then” scene from “Dude, Where’s my Car”…And then? I hope you find it useful to write better scenarios too… And then? And then? And theeeeeeeeeeeeen! And thenandthenandthen!

 

Special thanks to Andy Palmer for reviewing this blog post and helping me say it with fewer words.

Photo of the github page

Cucumber – with step-free access

A while back I wrote about writing feature specs (acceptance tests) at the right level of abstraction. I explained how we want to pitch our scenarios at the “task” level…

Goal: What we’re trying to achieve which has one or more…
Tasks: The high-level work-item that we complete to fulfil the goal, each having one or more…
Actions: The specific steps or interactions we execute to complete the task.

I showed how many scenarios (acceptance tests) are pitched at too low a level. They’re often at the action level, detailing every field filled in and every button clicked. This is too low-level.

Instead, we want to express the business process… the tasks involved in fulfilling a goal. The actions should be expressed in the code (or step-definitions), not the plain-text scenarios. Pitching the scenarios at the action level makes scenarios much harder to maintain – especially when the user-interface changes. But, perhaps more importantly, they don’t express what’s of interest to the business.

There are other challenges faced by teams using cucumber:

  • Over-wordsmithing scenarios
  • Limited regular-expression expertise
  • Unmaintainably large step-definition files
  • Fragmented step-definition files
  • Coverage vs. Speed tradeoffs of running scenarios through or below the GUI (respectively)

We’ve taken many of the lessons we’ve learned using BDD tools to address these problems and begun to distill the various heuristics and design ideas (patterns) that emerged into a single open-source extension to cucumber – cukesalad.

Photo of the github page

Many of the heuristics and design ideas expressed in the project can be used on your existing projects without using cukesalad:

  • Treat each step-definition as a class of task. Like other classes, have one file per step-definition and organise them so they’re easy to find. Name each file using the text used in the scenario.
  • Screen Capture of Task folder Hierarchy

  • Abstract the API that drives your application behind something representing the role or type of role involved in the story
  • Write scenarios like a narrative for someone in the role relevant to the user-story
  • Write the actions within the task (or step-definition) as if they’re instructions on how to complete that task
  • And more…

Cukesalad is the ongoing expression of us mercilessly refactoring a ‘typical’ Cucumber project. At the moment, it is more of an illustration of the concepts and ideas… but some are already using it on their day-to-day projects. Check it out… try it out… and let us know what you think.

Go to http://cukesalad.info – for more info, or checkout the talk I gave at CukeUp, hosted at SkillsMatter.

And if you’re wondering why it’s called cukesalad… It’s cucumber, washed and ready to eat.

 

A bit of UCD for BDD & ATDD: Goals -> Tasks -> Actions

There’s something wrong with many behaviour specs (or acceptance tests). It’s been this way for some time. I’ve written about this once or twice before, referencing this post by Kevin Lawrence from 2007.

So, first things first, I want to take this opportunity to update the terminology I use…

Goals -> Tasks -> Actions
A useful technique used in User-Centred Design (UCD) and Human Computer Interface (HCI) design is Task Analysis. There are three layers of detail often talked about in Task Analysis:

Goal: What we’re trying to achieve which has one or more…
Tasks: The high-level work-item that we complete to fulfil the goal, each having one or more…
Actions: The specific steps or interactions we execute to complete the task.

Previously, the terms used by Kevin, myself (and several others) were Goal->Activities->Tasks. From now on, I’m going to use the UCD/HCI/Task Analysis terms Goal->Task->Action. It’s exactly the same model – just with different labels at the three layers of detail.

What’s wrong with your average behaviour spec?
Let’s look at a common example… The calculator. For convenience, I’m going to borrow this one from the cucumber website[1].

Scenario: Add two numbers
Given I have entered 10 into the calculator
And I have entered 5 into the calculator
When I press add
Then the result should be 15 on the screen

[1]note: I’m using this example for convenience and simplicity. The value of the example on the cucumber website is to demonstrate how easy cucumber is to use and not necessarily as an exemplar feature spec

What would you say the scenario’s name and steps are representing? Goals and Tasks or Tasks and Actions?

I’d argue that adding two numbers is a task and the steps shown above are actions.

Instead, I try to write the spec (or test) with a scenario-specific goal and the steps as tasks.

Scenario: sum of two numbers
When I add 10 and 5
Then I should see the answer 15

I.e.:
Scenario: <A scenario specific goal>
Given <Something that needs to have happened or be true>
When <Some task I must do>
Then <Some way I know I've achieved my goal>

Another Typical Example
Let’s apply this to another typical example that might be closer to what some people are used to seeing:

Scenario: Search for the cucumber homepage
Given I am at http://google.com
When I enter "cucumber" into the search field
and click "Search"
Then the top result should say "Cucumber - Making BDD fun"

Again this is talking in terms of actions. As soon as I’m talking in terms of click, enter, type or other user-action, I know I’m going into too much detail. Instead, I write this:

Scenario: Find the Cucumber home page
When I search for "Cucumber"
Then the top result should say "Cucumber - Making BDD fun"

Why does it matter?
In the calculator example, the outcome the business is interested in for the first scenario is that we get the correct sum of two numbers. The steps in the scenario should help us arrive at a shared understanding of what ‘correct’ means. How we solve the problem of getting the numbers into the calculator and choosing the operator is a separate issue. That’s detail we can defer. It may be better to explore the specifics of the workflow using, sketches, conversation, wire-frames or by seeing and using our new calculator.

So, expressing our scenarios in terms of goals and tasks helps the delivery team and the business arrive at a shared understanding of the problem we’re trying to solve in that scenario.

Expressing the scenario in terms of the clicks, presses and even fields we’re typing into is focusing on a solution, not the problem we’re trying to solve.

But there’s another benefit to doing it this way…

A Practical Concern – Maintainability
The first calculator example follows reverse-polish notation for the sequence of actions:

  1. enter the first number
  2. enter the second number
  3. press add

If we put that detail in the scenarios, that workflow will be repeated everywhere – for addition, subtraction, division, multiplication… and anywhere any calculation is described.

What happens if the workflow for this calculator (such as the UI or API) changes from a reverse-polish notation to a more conventional workflow for a calculator? Like this:

  1. enter the first number
  2. press add
  3. enter the second number
  4. press equals

The correct answer hasn’t changed – i.e. the ‘business rule’ is the same – it’s just the sequence of actions has changed.

Now we have to go through all the feature files and update all the scenarios. In the case of our calculator that may only be a few files covering add, subtract, divide, multiply. For something larger and more complex this could be a lot of work.

Instead, putting this in the code of the step-definition means that this:

When ^I (add|subtract|divide|multiply) (.*) (?:and|from|by)? (.*) do |operator, first_number, second_number|
@calc = @calc ||= Calculator.new
@calc.enter first_number
@calc.enter second_number
@calc.send operator.to_sym
end

Would have to change to this:

When ^I (add|subtract|divide|multiply) (.*) (?:and|from|by)? (.*) do |operator, first_number, second_number|
@calc = @calc ||= Calculator.new
@calc.enter first_number
@calc.send operator.to_sym #moved up from the bottom
@calc.enter second_number
@calc.calculate #new action for the conventional calculator workflow
end

Nothing else would need to change – other than the product of course. By writing the steps as tasks, all of our feature files would still accurately illustrate the business rule even though the workflow of the interface (gui or api) has changed.

Taking your scenario-steps to task
So, taking this approach helps us to reduce our maintenance overheads. Putting the Actions inside the step definition makes our tests less brittle. When the workflow changes we only need to update our specs in one place – the step-definitions.

Of, perhaps, greater importance – by capturing the user’s scenario-specific goal as the scenario name and the tasks as the steps, the team are working towards a shared understanding of the part of the problem we’re trying to solve not a solution we might be prematurely settling upon. When rolled up with the broader context (expressed in the user-story and its other scenarios) it gives us a focus on solving the wider problem rather than biasing the solution.

Sometimes, at first, it’s hard to see how to express the scenario and is easier when people start by talking of clicks, presses and what they’re entering. And that’s ok. Maybe that’s where the team needs to start the conversation. Just because that’s where you start, ask “why are we doing those actions” a few times, and it doesn’t have to be where you end up.

You’re almost cuking it…

In “You’re Cuking it Wrong”, Jonas Nicklas, shows several examples of bad scenarios (or acceptance tests whichever term you prefer) and demonstrates better approaches. This is an excellent post on common mistakes made when writing example scenarios with Cucumber.

I think, however, he could have gone further in one case. One of his examples of a bad scenario looks like this:

Scenario: Adding a subpage
Given I am logged in
Given a microsite with a Home page
When I click the Add Subpage button
And I fill in "Gallery" for "Title" within "#document_form_container"
And I press "Ok" within ".ui-dialog-buttonpane"
Then I should see /Gallery/ within "#documents"

(Dude – yep, seen these… I agree… not good). He goes on to suggest it should really look like this:

Scenario: Adding a subpage
Given I am logged in
Given a microsite with a home page
When I press "Add subpage"
And I fill in "Title" with "Gallery"
And I press "Ok"
Then I should see a document called "Gallery"

This is a massive improvement. It keeps the specifics that inform the reader and give them some context (like filling in the “Title” with “Gallery”) and takes them further away from the implementation. Although it gets closer to expressing customer intent, I think it could go further. At the moment, it is describing the ‘what’ and some of the ‘how’. This example makes complete sense if what we are exploring is the design of the UI. I’ve not found these scenarios to be a good place to do that, however.

Instead, in these specifications we want our examples to illustrate the customer intent. The ‘what’ not the ‘how’. There are other places we can capture the ‘how’ – i.e. in the step methods.

Instead, I would write it like this:

Scenario: Adding a subpage
Given a microsite with a home page
Given I am logged in
When I Add a Subpage with a Title of "Gallery"
Then I should see a document called "Gallery"

I’ve removed all the “Tasks” and left only “Activities”. This leaves the user experience completely open. This ensures that when there are UI changes, I only change the code that performs the tasks (clicking, pressing, etc.) and my scenarios evaluate whether the customer intent is still fulfilled – without having to go back and change a lot of files.

Otherwise – great post Jonas :-)