Easy PlainText Stories in Ruby on Rails using WebRat

Building off of my last post on Stories, I’d like to show you some improvements I was able to make with the help of WebRat.

You can install WebRat using:

script/plugin install http://svn.eastmedia.net/public/plugins/webrat/

I got the inspiration from Ben Mabey at ‘ben.send :blog’ which illustrates an approach to stories that is unbelievably easy to pick up. He also provides source code to the example that he’s built so that you can play with it. Very cool!

I snagged that source myself and started playing with it, and added a lot of functionality of my own that I found useful. The real cool thing is that the ONLY application specific code I have is this:

# user_steps.rb
steps_for(:user) do
  
  Given("that $actor is not logged in") do |actor|
    get "/sessions/destroy"
    response.should be_redirect
    flash[:notice].should == "You have been logged out."

    #fails here even though in the next request it will pass
    #controller.should_not be_logged_in
  end
  
  Then("$actor $should be logged in") do |actor, should|
    controller.send(shouldify(should), be_logged_in)
  end
  
end

# navigation_steps.rb
def path_from_descriptive_name(page_name)
  case page_name
  when "home"
    ""
  when "signup"
    "users/new"
  when "login"
    "sessions/new"
  else
    "#{page_name}"
  end
end

With that, and the generic application-independent helper methods that also live in my steps directory, I can write the following story:

Story: Making posts

  As a visitor
  I want to be a member
  So that I can make posts

    Scenario: Glenn creates a new account
      Given that Glenn is not logged in
      And there are some number of users
      And no user with login 'Glenn' exists
      
      When he goes to the signup page
      And fills in Login with 'Glenn'
      And fills in Email with 'glenn@glennfu.com'
      And fills in Password with 'blah'
      And fills in Confirm Password with 'blah'
      And clicks the 'Sign up' button

      Then there should be 1 more user
      And a user with login 'Glenn' should exist


    Scenario: Glenn logs in
      GivenScenario Glenn creates a new account

      When Glenn goes to the login page
      And fills in Login with 'Glenn'
      And fills in Password with 'blah'

      Then he should be logged in
    
    
    Scenario: A member makes a post while logged in
      GivenScenario Glenn logs in
      And there are some number of posts

      When he goes to the posts page
      And clicks on 'New post'
      And fills in Title with 'Woo'
      And fills in body with 'Stuff here'
      And clicks the 'Create' button

      Then there should be 1 more post
      And a post with title 'Woo' should exist


    Scenario: A nice lady makes a post while not logged in
      Given that she is not logged in
      Then she should not be logged in

      Given there are some number of posts

      When she goes to the posts page
      And clicks on 'New post'

      Then she should see the login page


    Scenario: An angry visitor should be able to see posts
      Given that he is not logged in

      When he goes to the posts page

      Then he better not f'ing see the login page


    Scenario: A visitor should not be able to edit posts
      GivenScenario A member makes a post while logged in
      And that she is not logged in

      When she goes to the posts page
      And clicks on 'Edit'

      Then she should see the login page

Pretty cool, huh? I was even able to add some personality with the angry visitor Scenario. Notice that I don’t have any steps written about Posts or my PostsController. I don’t need it because I have generic model steps that parse the model from the text in my PlainText instructions. It has all the basics that you need. You interact with forms and links on the top level by name, and then check the results either by text on the page or by finding models.

If you’d like to play with it yourself, I’ve zipped up my stories folder for you to play with.

Download it here!

It also has the old user_story.rb from the previous example. If you have any suggestions for improvements to this or ideas for something else I should do with it, please leave a comment!

My only quirk with this is that if you check the first step in the steps_for(:user) above you’ll see I have a line commented out. It checks for controller.should_not be_logged_in and if I uncomment it, the check fails even though the two above it pass. As you can see in the PlainText, on the very next line I call the very same check and it passes. If you could help me figure out my mistake here I’d really appreciate you leaving a comment with your thoughts!

I hope you find this useful, and if so, be sure to go toss a thank you over to Ben for the inspiration.

5 comments ↓

#1 John Ford on 03.31.08 at 11:21 am

Thanks for the great example code! I can’t wait to play with this more. I’m really enjoying Stories and WebRat.

#2 Brandon Burke on 04.11.08 at 1:19 pm

This is a really neat concept – looks relatively easy to implement for all of the functionality that it provides too. I’m interested in using it as soon as my rails development picks back up. Thanks again for providing a great intro to Stories and Webrat!

#3 Bryan Helmkamp on 08.11.08 at 11:10 pm

Just a quick update…

Webrat has moved to GitHub. The latest source can be found at:

http://github.com/brynary/webrat

Cheers,

-Bryan

#4 Glenn Ford on 08.13.08 at 1:07 pm

Thank you Bryan!

#5 A Fresh Cup » Blog Archive » Double Shot #304 on 10.02.08 at 5:13 am

[...] Easy PlainText Stories in Ruby on Rails Using WebRat – More work on smart stories. [...]