2009-06-18

Cucumber

Plain text integration tests (i.e. FIT) never worked for me. It's just too costly to create and maintain the fixtures.

Cucumber changes the cost-benefit ratio. With Cucumber and Rails, the cost of maintaining the fixtures is so low that I no longer bother writing conventional Rails controller and integration tests. For any testing at the controller level and up, I use Cucumber.


Here's a conventional Rails integration test:
class UserStoriesTest < ActionController::IntegrationTest
  context "A user" do
    setup do
      @admin = Factory.create(:user, :is_admin => true)
      @non_admin = Factory.create(:user,
        :is_admin => false)
    end

    should "be able to login as an admin and set another user to be admin" do
      user = regular_user
      user.logs_in_as(@admin)
      user.views_users
      user.edits_user(@non_admin)
      user.makes_user_an_admin(@non_admin)

      non_admin = User.find_by_id(@non_admin.id)
      assert non_admin.is_admin?
    end
  end

  def regular_user
    open_session do |user|
      def user.edits_user(user_edited)
        get "/admin/users/#{user_edited.id}/edit"
        assert_response :success
        assert_template 'admin/users/edit'
      end

      def user.logs_in_as(user_login)
        get '/login'
        assert_response :success
        assert_template 'user_sessions/new'

        post_via_redirect '/user_sessions/create',
          :user_session => {
            :email => user_login.email,
            :password => user_login.password }
        assert_response :success
        assert_template 'posts/index'
      end

      def user.makes_user_an_admin(user_updated)
        post_via_redirect "/admin/users/update",
          :id => user_updated.id,
          :user => { :is_admin => true }
        assert_response :success
        assert_template 'admin/users/index'
      end

      def user.views_users
        get '/admin/users'
        assert_response :success
        assert_template 'admin/users/index'
      end
    end
  end
end

Here's the Cucumber equivalent:
Scenario: Set non-admin user to admin
  Given a user is logged in as admin
  And a non-admin user "Peter"
  When I go to the list of users
  And I fill in "search" with "Peter"
  And I press "Search"
  And I follow "Edit"
  Then I should see "Peter"
  And the "Is Admin" checkbox should not be checked
  When I check "Is Admin"
  And I press "Save"
  And I go to the list of users
  And I fill in "search" with "Peter"
  And I press "Search"
  And I follow "Edit"
  Then I should see "Peter"
  And the "Is Admin" checkbox should be checked

Reference: