Imperative vs Declarative Scenarios in User Stories

Last week I was looking at some of the presentations from GoRuCo that Confreaks recently posted. One of them was a presentation on rspec's story runner given by Bryan Helmkamp's (of webrat fame.) It is a great presentation which I highly recommend for anyone looking into incorporating the story runner into their development process. In the presentation Bryan talked about the differences between imperative and declarative scenarios. In my opinion, both styles have benefits and should be used appropriately based on the situation. The majority of examples on rspec's story runner currently on the web, including mine, are of the imperative type. Since the declarative type has many advantages I thought it would be worth while to present some examples and contrast the differences between the two styles.

Imperative Style

Lets look at the example I gave in my previous post (slightly modified):

Story: Animal Submission

  As a Zoologist
  I want to add a new animal to the site
  So that I can share my animal knowledge with the community

  Scenario: successful submission
  Given I'm on the animal creation page

  When I fill in Name with 'Alligator'
  And select Phylum as 'Chordata'
  And fill in Animal Class with 'Sauropsida'
  And fill in Order with 'Crocodilia'
  And fill in Family with 'Alligatoridae'
  And fill in Genus with 'Alligator'
  And check Lay Eggs
  And click the Create button

  Then I should see the notice 'Thank you for your animal submission!'
  And the page should include the animal's name, phylum, animal class, order, family, and genus

The imperative style uses highly reusable granular steps which outlines much of the user interface. This binds the scenario to that interface and requires more design decisions made up front. The step matchers for these granular steps are very easy to write as I demonstrated in my webrat post. Once these steps are in place you can write the majority of your scenarios in this fashion without having to write custom step matchers. Due to the granularity of the scenarios however they become very brittle as they are subject to requirement changes from the customer. If a new field is added, for example, you must update the scenario to reflect this even though the underlying goal of the scenario has not changed.

Declarative Style

Lets rewrite the above example in a more declarative fashion. The story narrative and scenario title will remain the same.

Story: Animal Submission

  As a Zoologist
  I want to add a new animal to the site
  So that I can share my animal knowledge with the community

  Scenario: successful submission
  Given I'm on the animal creation page

  When I add a new animal

  Then I should see the page for my newly created animal
  And the notice 'Thank you for your animal submission!'

This style is more aligned with User Stories in the agile sense having more of the "token for conversation" feel to it. The first thing that you should observe about this style is how much smaller it is than the imperative one. This is a good thing. The imperative style tends to produce noisy scenarios that drown out the signal. With the declarative style the goal of the scenario remains clear. When a new field is added to the form the scenario does not have to be modified. Yes, you will have to modify the underlying step matcher but the scenario does not have to suffer dilution due to the change. The trade off is, of course, that you will now be writing step matchers for all of your scenarios. Looking at our example, the implementation for the When step is very similar to the imperative scenario steps:

# animal_steps.rb
When "I add a new animal" do
  fills_in 'Name', :with => 'Alligator'
  selects 'Chordata', :from => 'Phylum'
  fills_in 'Animal Class', :with => 'Sauropsida'
  fills_in 'Order', :with => 'Crocodilia'
  fills_in 'Family', :with => 'Alligatoridae'
  fills_in 'Genus', :with => 'Alligator'
  checks 'Lay Eggs'
  clicks_button 'Create'
end

The majority of the imperative step matchers were merely wrappers for webrat so creating custom steps for each scenario is not much of a deterrent. Additionally, the reuse of steps will only take you so far before your stories start to feel unnatural as you try to force each scenario to use the same phrasing. Creating custom steps for each scenario actually turns out to be better for reducing duplication in most cases. That is because you can now extract duplicate code from the step matchers into helper methods. The place to put these helpers is in the Spec::Story::World module (monkey patch it.)

Another way to reduce duplication in step matchers that I learned recently is to call other steps directly within another one. For example, if you have this step:

Given "a user named $user_name" do |user_name|
  User.create!(:name => user_name, ....)
end

and you now want to have a step that matches 'Given a user named Jim with a photo album' you can reuse the above step directly in the new one like so:

Given "a user named $user_name with a photo album" do |user_name|
  Given "a user named #{user_name}"
  ....
end

I haven't experimented with this approach too much so I'm not sure how much I like it, but I can see occasions where it would prove useful.

Choosing which style to use

I have made a strong case for the declarative style of writing scenarios. It would seem that one should never write a scenario imperatively based solely on the merits of maintenance and communicating story intent. While I think the declarative style has many strengths it is not the best choice for all situations. The imperative style should not be discounted entirely because when used judiciously in the right scenario it can highlight certain aspects of the functionality and improve communication. It is also important to realize that the two types are not mutually exclusive. The styles can be mixed throughout an app, a story, and even an individual scenario to provide the appropriate level of granularity as the situation demands.

One of the most important factors in deciding which type of style to adopt however has nothing to do with maintenance or code duplication; that factor is the customer. While these stories may be acting as integration tests for the developer that is not the original purpose. The stories are meant to facilitate communication between developer and stakeholder about business value and functionality. If your stakeholder needs each form field outlined in the scenario in order to have confidence in the system then the imperative style is a better route to go. Specs (unit tests) are just for the developer but stories need to appease the wider audience of developer and stakeholder so an appropriate balance needs to be reached. As in most areas of software development there is no right answer and in the end it just depends on the situation.

References

Aside from the materials already linked to in this post another great resource (actually, it is the best that I have found) on the various ways to approach story runner is David Chelimsky's ETEC slides. In the slides he refers to the imperative style as detailed scenarios. He will be giving a similar talk at at RailsConf, so be sure to catch it if your able to make it to RailsConf this year.

I'd like to thank David Chelimsky, Kyle Hargraves, and Zach Dennis for their discussion on this topic on the rspec-users mailing list.


About this entry