With Cucumber, you write stories and user acceptance tests in plain English, something a lot of people seem to like.
Feature: Search
As a user
I want to find information
So I can learn more
Scenario: Find what I'm looking for
Given I am on the Google search page
When I search for "rspec"
Then I should see a link to RSpec-1.2.4: Home
Then you need to write your “step” files, where you add blocks with regular expressions that must match your plain English user stories and user acceptance tests. Inside those blocks you add your actual Ruby code. If you are using Cucumber for testing Rails or Sinatra, then your step definitions will look like this:
Given 'I am on the Google search page' do
visit('http://www.google.com/')
end
When /I search for "(.*)"/ do |query|
fill_in('q', :with => query)
click_button 'Google Search'
selenium.wait_for_page_to_load
end
Then /I should see a link to (.*)/ do |expected_url|
click_link expected_url
end
Now that you have your plain English features files and your step files, you can finally run your tests. As a result, you will get a nice output of the user stories and user acceptance tests in plain English. But just to clarify that: the output is the same plain English stories you wrote at the beginning. The cost for this is to keep in sync two files for mostly the same thing.
In Citrusbyte we have a different workflow. We agree on the user stories with the client, and we put into instructions the user acceptance tests. We do that using Stories, which is a small add on for Contest. It allows you to declare user stories, scenarios and steps using Webrat. The same example, this time with Stories, would look like this:
class SearchStoriesTest < ActionController::IntegrationTest
story "As a user I want to find information so I can learn more" do
scenario "Find what I'm looking for" do
visit "http://www.google.com/"
fill_in "q", :with => "Citrusbyte Stories"
click_button "Google Search"
assert_contain "citrusbyte's stories"
click_link "citrusbyte's stories at master - GitHub"
assert_contain "Stories and User Acceptance Tests"
end
end
end
When you run that with the stories runner, you get this output:
As a user I want to find information so I can learn more
— Find what I'm looking for
Go to “http://www.google.com”
Fill in “q” with “Citrusbyte Stories”
Click “Google Search”
I should see “citrusbyte's stories”
Click “citrusbyte's stories at master - GitHub”
I should see “Stories and User Acceptance Tests”
Now you can redirect that output to a text file and email it to your client, or you can use the stories-pdf runner, send the PDF straight to your client and get a delicious cake in return. Don’t believe me? Check this post.
You will have all your tests in one place, you will be writing Ruby, your clients will be happier than ever and the overhead will be minimal. Grab the gem from github and start impressing your clients today!

{ 1 trackback }
{ 13 comments… read them below or add one }
The main benefit IMO of separating steps and user stories is reuse, with your approach in ‘Stories’ you won’t be able to reuse steps between different scenarios. As the cucumber features grow, I’ve found this to be particularly useful to avoid duplication.
Nice! I usually end up ditching Cucumber and just writing my tests in plain webrat. For some extra sugar I’ve been using http://github.com/foca/storyteller until now, but I really like your textual formatting of the webrat actions. Good work!
I wouldn’t consider this a Cucumber alternative. What you’ve got here is equivalent to doing WebRat acceptance tests in RSpec - something that some people do, and there’s nothing wrong with it. But it’s a different level of abstraction than Cucumber.
@Michael: Code reuse is easy and we do it all the time. You only need to extract the repeated steps to a helper method, so instead of writing the same steps for, say, login, you just do login(@user) and you are done. You reuse code as you would in any Ruby program, by factoring out helper methods.
@Harry: Thanks a lot! I’m glad you like it. Storyteller’s author, foca, is a great friend of mine and we share the philosophy for small and efficient tools.
@Avdi: I think Cucumber gives you a false sense of abstraction, when in reality it’s just saying the same thing twice (in plain text and in code). I consider Stories a Cucumber alternative because it “serves as documentation, automated tests and development-aid”, which is Cucumber’s goal as stated in its website. And it does all that without requiring a huge library like Cucumber, that needs a Treetop parser and formatters because it wants to go from natural language to code, which in my opinion is not wise at all.
First, only a programmer could think Cucumber and Rspec code are similar. One is readable by mere mortals, the other raises more questions than it answers. (What’s “q”? That is an impementation detail that shouldn’t be at the top level.)
Scenario: Find what I'm looking forGiven I am on the Google search page
When I search for "rspec"
Then I should see a link to RSpec-1.2.4: Home
visit "http://www.google.com/"fill_in "q", :with => "Citrusbyte Stories"
click_button "Google Search"
assert_contain "citrusbyte's stories"
click_link "citrusbyte's stories at master - GitHub"
assert_contain "Stories and User Acceptance Tests"
Second, the real world tends to be quite a bit more complex. The URLs are more complicated, the text is longer, there are more form fields, etc. In this case, you’d probably make a subroutine to hold the most of your assertions anyway.
Yes, Cucumber forces you to make every step a subroutine. But that gives you a chance to hide the implementation details, plus gives you much better naming of things.
@Anonymouse: Both Cucumber and Stories use Webrat for defining the steps, which is what you quoted below the plain English Cucumber features. No matter which library you use, you still need to write fill_in “q”, :with => “rspec” somewhere.
If you are using Cucumber, you will write:
…in one file. Then, in another, you have to add this:
…and finally this:
fill_in('q', :with => query)That is, in my opinion, three ways of saying the same thing. With Stories you only need to write that last part, because the text generation is automatic.
I understand your point, though: sometimes you want to hide the implementation details like “q”. We have a solution for that:
report "When I search for 'Citrusbyte Stories'" do fill_in "q", :with => "Citrusbyte Stories" click_button "Google Search" endHere is what report does: it silences the normal output and replaces it with the string you pass it. It’s very handy for the case you mentioned, but also when you want to group steps together.
You also said that Cucumber gives you much better naming of things, but you are free to write your own step definitions. To show this, I will cover your point about subroutines. Suppose you are testing Google and you do a lot of different searches. You would want to reuse the fill_in and click_button steps, so you write a search helper:
def search(str) report "When I search for #{str}" do fill_in "q", :with => str click_button "Google Search" end endNow each time you use search you get a better message in your output. And you had to write it only once, while with Cucumber you write it every time.
If you want to add messages for your own helpers or assertions, you can also use the report_for method. We have the following assertion in our test_helper:
def assert_email_sent_to(recipient) assert_equal Array(recipient), ActionMailer::Base.deliveries.last.to endThen, in order to have a nice message, we added this:
module Stories::Webrat report_for :assert_email_sent_to do |email| "An e-mail should be sent to #{quote(email)}" end endAnd the result is the same as if we were using any already defined assertion.
These are customizations that you will rarely do, but it’s good to have the ability to change the way you are presenting your user stories. Needless to say, when you need to change some text you do it in only one place.
All in all, the idea behind Stories is to make a more efficient use of your time by letting the program do the work for you.
Totally agree with post author. I always wondered who could spend so much time writing all those “When” and “Then” clauses just to use it in one story (or maybe two stories). IMO, it’s all bullshit that mere mortals can write somewhat complicated spec with Cucumber, because in fact he will need many different Whens and Thens.
So, I consider Cucumber just a tool for writing easy to read documentation (”stories”). And this tool does that perfectly. And also, it doesn’t distract developer with need to define another layer of abstraction. And did I mention that I love it being more lightweight than Cucumber ?
@Maxim Kulkin: I agree with you and I’m glad you like this tool. Thanks for your comment!
Hello Michel,
As a Ruby newbie and a non Rails user, I would like to know if Stories (and Contest too) could be used with Watir to do test automation (Acceptance tests) .
Having looked over Cucumber, Shoulda, and Coulda, Stories and Contest seem to me to be more of the route I want to follow to do my testing.
Thank you!
Hello Michel,
I have left previous comments but not sure why they are not showing up.
As I am a Ruby Nuby and new to the world of Unit/Acceptance Testing, I would like to ask how Stories (and Contest) work with Watir. My company does not have any Rails or Sinatra projects but does have websites using ASP.Net. I would like to use Stories as a test framework but am not familiar enough with Webrat. The websites do have a lot of AJAX and Javascript so I do not believe that Webrat would work.
Stories and Contest seem to be the best fit as they build on the Test::Unit::Testcase already available in Ruby and seem to be easier to follow than say Cucumber/Shoulda/Coulda.
Thank you in advance,
Michael
This looks very nice. I’ve spent time with FitNesse and the Java and Ruby versions of Concordion. The former requires everything be put in tables. The latter two allow free form as well as tables, but require instrumenting HTML, a potentially tedious process. After using Ruby Concordion for a while, I went to plain ol’ Test::Unit and felt freer. I have not tried Cucumber, but I have heard from a couple of users that spec maintenance can be a bit of a pain.
The point with tools such as FitNesse, Cucumber, and Concordion is that they provide a mechanism for non-programmers to write tests. In the projects I’ve worked on, however, it seems the programmers end up writing the acceptances tests anyway. So perhaps for some teams, having a DSL is not all that important.
Any thoughts about how to approach a story that has several scenarios that differ only by a few values, while precluding a lot of duplication? FitNesse definitely and perhaps Concordion and Cucumber would use tables.
@Michael Heinrich: I haven’t tried it with Watir, and I’m not familiar with it either, but I would say it should work. And if it doesn’t, an adaptation should be very straight forward.
@CRG: I’d say helpers are the way to go for removing duplication. You can define the helpers globaly or for each context, and in any case it let’s you abstract common patterns very quickly.
For people who are using Cucumber and Rails, you can use the cucumber rails gem to achieve what Stories does.
http://github.com/aslakhellesoy/cucumber-rails/tree/master/templates/install/step_definitions/