Peter Marklund

Peter Marklund's Home

Wed May 23, 2007
Programming

Rails + RSpec: First Impressions

I started using RSpec on a client project yesterday and I've been pleasantly surprised by how easy it is to get started with and how nicely it plays with Rails. I now have a handful of specs under the spec directory and they get run by rake automatically right after my tests. I can also use rake spec:doc to generate the documentation of my specs:

$ rake spec:doc

Admin::StatisticsController
- Index page is not viewable by role user or role admin without service id
- Index page, role user: shows links
- Index page, role super: shows links
- Hours page, role user: does not show customer and service selects
- Hours page, role super: selects service when service provided
- Hours page, role super: selects service when service and customer provided
- Hours page, role super: selects customer when customer provided

the Call model
- Is not deleted by attempt to delete customer
- Is not deleted by attempt to delete service

the Service model
- Is not deleted by attempt to delete customer

I decided to not prefix all my specifications with the "should" keyword, it seemed superfluous. Here are some samples from my controller spec:

require File.join(File.dirname(__FILE__), "/../../spec_helper")

describe Admin::StatisticsController do
  fixtures :customers, :services, :users, :services_users, :audio_files, :prompts, :calls  
  integrate_views

  specify "Index page is not viewable by role user or role admin without service id" do
    login(:user)
    get :index
    response.should be_error

    login(:admin)
    get :index
    response.should be_error
  end
  
  specify "Index page, role user: shows links" do
    login(:user)
    get :index, :id => 2
    response.should be_success
    response.should have_tag("a[href=/admin/statistics/hours/2]")
    response.should have_tag("a[href=/admin/statistics/calls/2]")
  end
  ...

  ######################################################
  #
  # Helper methods
  #
  ######################################################

  def login(role)
    login_user(user_for_role(role))
  end

  def user_for_role(role)
    case role
    when :super
      users(:aaron)
    when :admin
      users(:admin)
    when :user
      users(:customer)
    else
      raise "Unknown role #{role}"
    end
  end
  
  def login_user(user)
    @controller.send(:session=, ActionController::TestSession.new)
    @controller.send(:current_user=, user)
  end
end

I think it's very refreshing to switch to RSpec from unit tests. The syntax is more readable and makes it feel natural to write specs/tests before the code. In this particular case though I wrote the spec first, but when I started implementing the UI I changed my mind about which page the form should go on, experimented with the UI a bit, and ended up writing the spec after the fact. I don't consider this a deadly sin. One probably shouldn't be too religious about writings specs before the code in cases where it slows you down too much or hinders your creativity.

I highly recommend you try out RSpec with Rails if you haven't already.

Comments

Mathias said over 7 years ago:

If you have not made to many specs yet i recommend upgrading rspec to 1.0.

It's some heavy development going on with the rspec project and they just released 1.0 and now 'specify' is just called 'it'.

So if you do not have to many specs, upgrade and change them now, before it is to late ;-)

Cheers!

/mathias

--------------------------------------------------------------------------------