Cucumber: imperative or declarative? that is the question

imperative results

I’ve recently been putting some amount of thought into how to write good Cucumber features. One the reasons I love Cucumber so much is its language focus; meaning it makes you think about things like sentence function more than other testing frameworks I have used. One element of sentence function usage in Cucumber that’s important is whether you should write imperative (communicative) or declarative (informative) sentences for your steps. I’ll provide a couple of examples to show the differences.

An imperative (communicative) Cucumber scenario

Scenario: Submit the form with correct data (imperative)
  Given I am on the watir example form
  When I set "What is your name?" to "Alister"
  And I set "What is your story?" to "I like ruby"
  And I set "What testing tool do you like?" to "Watir"
  And I click "Submit"
  Then I should see the message "Thanks! Your response has been recorded."

Each step is a command, or instruction, so it’s pretty clear what is being done.

A declarative (informative) Cucumber scenario

Scenario: Submit the form with correct data (declarative)
  Given I am on the watir example form
  When I submit the form with correct data
  Then I should see the correct message

Each step states an idea, so sometimes it’s not really clear precisely what is being done.

Imperative vs Declarative

There’s some quite good articles about writing Cucumber features/scenarios around. One such article that stood out to me was written in May 2008 about RSpec Story Runner, and whether you should use an imperative or declarative style. The answer is, of course, it depends, but most people tend to lean towards the declarative style, just the way that a lot of programmers prefer declarative programming. I am actually swinging towards imperative style cucumber features and steps; the reasons for which I will explain below.

Running Imperative Features gives you richer output

With the two examples above, I have kinda cheated, in that the step definitions for the declarative style calls imperative steps. For example, this is the declarative step defintion:

When /^I submit the form with correct data$/ do
  When "I set \"What is your name?\" to \"Alister\""
  And "I set \"What is your story?\" to \"I like ruby\""
  And "I set \"What testing tool do you like?\" to \"Watir\""
  And "I click \"Submit\""

This is all well and good, as you can now have multiple cucumber steps that call the same thing, it’s DRYish, but the problem is when you run the step “When I submit the form with correct data”, that’s all you get.

Compare this to the imperative step results, which whilst calling exactly the same code, give you a lot more richness.

Writing imperative scenarios allow you to utilise things advanced cucumber functionality

Two table based Cucumber features I like using are scenario outlines, and multiline step arguments, but these don’t make a lot of sense if you’re using a declarative style.
For example, the imperative scenario could be easily adapted to use a scenario outline, whereas the declarative style would mean writing more declarative steps.

Scenario Outline: Submit the form with correct data (imperative - outline)
  Given I am on the watir example form
  When I set "What is your name?" to "<name>"
  And I set "What is your story?" to "<story>"
  And I set "What testing tool do you like?" to "<tool>"
  And I click "Submit"
  Then I should see the message "Thanks! Your response has been recorded."

   | name    | story       | tool     |
   | Alister | I Like ruby | Watir    |
   | Mozart  | I like java | Selenium |

Writing declarative scenarios often means hidden detail

As you move to more and more declarative scenarios, more and more details become hidden in cucumber step definitions and library code. As Rasmus pointed out on Jared Quinert’s blog on does Cucumber suck:

…tests end up looking like the one test to rule them all™:
Given everything is set up
When I submit correct data
Then everything should be OK


To wrap up, I’m not saying don’t go declarative, what I am saying is that you lose certain things in Cucumber when you do, but whether this is a big deal or not depends on what you’re trying to get out of it. In the meantime, I’ll continue to experiment and see what works and what doesn’t.

Author: Alister Scott

Alister is an Excellence Wrangler for Automattic.

9 thoughts on “Cucumber: imperative or declarative? that is the question”

  1. To me it is a matter of more detail or less. You need to consider (1) what is a more natural way for you to write out your test ideas? (2) what is easier to implement? and (3) what will be easier for others to understand when they review your tests. The whole point of cucumber, of course is #3 — communicating with developers and stakeholders.


  2. We’ve been having this discussion on my current client site. I think that both methods provide value; the difference, I feel, is when they provide value.

    Declarative is better when your describing the acceptable behaviour of the system. When you’re talking about the whether an implementation is acceptable then imperative would then be better.

    If you use declarative when you should be using imperative, like in your example, your tests become vague and provide little value.

    If you use imperative when you should be using declarative then your tests start to lose their value.

    Declarative tests define the acceptable behaviour of the system and therefore provide long living, versioned, ‘requirements’. Imperative tests tends to have more implementation detail in it; this can make it harder to understand the acceptance criteria (when used in the wrong place), it can also make the test brittle to change.

    For me; if I’m writing the acceptance criteria for a story then I try to stay as declarative as possible. If I’m working on something more UI or implementation specific then I’ll shift towards a more imperative style.


  3. So, as a newbie on BDD and cucumber, what I’m ‘assuming’ is that I should write my initial steps as declarative to setup ‘general’ stories and evolve to imperative steps for implementation and refactoring. Seems a good workflow. Is it?


  4. @ronaldo @alister if you’re doing ATDD then your acceptance tests will be defined by a BA/Tester pair and will probably be declarative in style. It’s bad form to change an acceptance test, even if making it more imperative makes it easier to implement. I’m taking your use of the word evolve to mean ‘change over time’. The reason it is bad form is the acceptance criteria needs to live on with the code to provide documentation of the systems intended behaviour. To change this can cause the behaviour to be lost in an imperative style test or a subtle change in the word can suggest a different behaviour that what was originally desired.

    If that’s in the RSpec book then I don’t agree with it and may have to find a copy to read. There is of course the distinction between BDD and ATDD to be resolve. It may be appropriate to evolve BDD tests as suggested. However I think there is much confusion floating around about what the difference between ATDD and BDD is, if there is any.

    I hope this clarified rather than confused.


    1. You make sense Ryan.
      You’re correct in that it suggests to evolve the BDD tests.
      It talks about creating the high level acceptance ATDD features, drilling down into evolving BDD tests (using RSpec), at which point your ATDD features should be passing.
      This is what I meant, I came across all wrong.


  5. It should be noted that there is now a ‘cucumber book’ out from pragmatic. They give a lot of very good reasons to not do imperative style features unless you are specifically expressing details that are critical to the business. One of them is that the scripts can be very brittle and require a lot of updating. Another is that the excessive detail makes it hard to read and difficult to communicate with the stakeholder. Features are ‘business facing’ and unless it’s important to express a high level of technical detail to the business, then it’s better to leave that stuff for the steps.

    Concerning your example above, if it’s important to the business to know exactly what fields and labels are provided on the form, then you probably should have a feature that details what elements should be present on that page (and you could make use of cucumber’s table capability to list out the elements, labels etc in a fairly compact and logical form.

    But in the example you provided, I would argue that the excess level of data prior to the submitting of the form is obscuring the business value that the scenario is looking for, which is more likely that the data is properly recorded, the confirmation message displayed, etc. (it’s hard to say since we are working in absence of a feature definition, so we do not know WHY the feature is being implemented or WHO it is implemented for, we have just the scenario in isolation)

    This might be a really good subject to discuss at the upcoming testing event in Austin


Comments are closed.