BDD Step-by-Step Example (part 1)

March 29th, 2009 by admin Leave a reply »

Before we can begin doing BDD (behavior driven development) we need to install some tools to help.

sudo gem install cucumber rspec-rails webrat

Next I go to my Rails application and run some scripts to get the basic set-up inside my rails directory structure:

script/generate rspec
script/generate cucumber

Now in the newly created features folder I will create a file called user_administration.feature. This file will contain all my scenarios for this feature. After spending some time thinking about how to express my features I come up with two basic ones to start:

Feature:  User Administration

So that I can control access to the application
As an admin
I want to manage users

Scenario: Create a new user account
  Given no user "joetest"
  When I create a new user "joetest" with password "skymonkey"
  Then the user "joetest" can log in with password "skymonkey"

Scenario: Suspend an existing user account
  Given a user that is active
  When I suspend the user
  Then the user can not log in

Now I run the following command to have cucumber generate snippet methods that I can then copy into a step definition.

script/cucumber features/user_administration.feature

I create a new file named user_steps.rb in the features/step_definitions folder. Now that we have our step definition snippets the next job is to take them from “pending” into something meaningful. We’ll start with the first scenario. After giving it some thought it might end up looking like this:

Given /^no user (.+)$/ do |login|
  lambda{ User.find(login) }.should raise_error(ActiveRecord::RecordNotFound)
end

This first part sets us up. It allows us to express the given state, in this case not finding a user named “joetest”.

When /^I create a new user "(.+)" with password "(.+)"$/ do |login, password|
  visit new_user_path
  fill_in "user_login", :with => login
  fill_in "user_email", :with => "#{login}@test.org"
  fill_in "user_password", :with => password
  fill_in "user_password_confirmation", :with => password
  click_button "Sign Up"
end

Next we describe the action we’ll be taking. This code simulate the submission of a form, using Webrat. We take this approach because it makes us exercise the whole stack views, controller and models. It’s just short of me going to the site with a browser.

Then /^the user "(.+)" can log in with password "(.+)"$/ do |login, password|
  visit login_path
  fill_in "login", :with => login
  fill_in "password", :with => password
  click_button "Log In"
  response.should contain("Logged in Successfully")
end

Lastly we test our outcome, that the user the admin created is able to log in. So the end result is test that describes the behavior of an admin creating a new account for a user, and they are able to successfully log in.

Along the way you may find tests go red (fail), this is normal. You want to write code (just enough) to make them go green, then continue to write more test code. Keep repeating this until all your tests run green.

Also the nice thing about step definitions is that they can be reused in other tests. We’ll likely have other scenarios where we create a new user or try to log in as one. Our code stays dry and we (the developer) stay confident. (Now it’s sounding like a anti-perspirant commercial, so I’ll stop now.)

Advertisement

1 comment

  1. Melvin Ram says:

    This is AWESOME! I have been looking for something like this and I just “got it.” Thank you!

Leave a Reply