Scenarios, an Alternative to Fixtures

Being fully aware of the work of Mr. Preston-Werner[1] and err.the.blog[2], we present to you Scenarios, a somewhat different approach[3] to alleviating the pain of managing table data for a Rails application under test.

A simple scenario looks like this:

  # in spec/scenarios/users_scenario.rb   class UsersScenario < Scenario::Base     def load       create_record :user, :john, :name => 'John', :password => 'doodaht'       create_record :user, :cindy, :name => 'Cindy', :password => 'whoot!'     end   end

To use the UsersScenario in an RSpec description, you should declare it using the scenario method:

  # in spec/models/user_spec.rb   describe User do     scenario :users

    it "should allow me to do something with John" do       user = users(:john)       user.password.should == "doodaht"     end   end

In real life your scenarios will probably grow quite complicated. The scenarios plugin allows you to deal with this complexity through composition.

Here's a simple example:

  # in spec/scenarios/posts_scenario.rb   class PostsScenario < Scenario::Base     def load       create_record :post, :first, :title => "First Post"       create_record :post, :second, :title => "Second Post"     end   end

  # in spec/scnearios/comments_scenario.rb   class CommentsScenario < Scenario::Base     uses :posts

    def load       create_record :comment, :first, :body => "Nice post!", :post_id => post_id(:first)       create_record :comment, :second, :body => "I like it.", :post_id => post_id(:first)       create_record :comment, :third, :body => "I thoroughly disagree.", :post_id => post_id(:second)     end   end

When you use a scenario, you get any help the scenario provides made available to your RSpec examples.

  # in spec/scenarios/users_scenario.rb   class UsersScenario < Scenario::Base     def load       create_user :name => "John"     end

    helpers do       def create_user(attributes={})         create_record :user, attributes[:name].downcase.intern, attributes       end       def login_as(user)         @request.session[:user_id] = user.id       end     end   end

  # in spec/controllers/projects_controller_spec.rb   describe "Projects screen" do     scenario :users

    it "should show active projects" do       login_as(users(:john))       get :projects       @response.should have_tag('#active_projects')     end   end

You can load your scenarios into your development database, too!

   rake db:scenario:load SCENARIO=comments

Scenarios works by doing direct inserts instead of using ActiveRecord instances - there is no validation - similar to the way the current fixtures implementation works.

You may find greater detail at the RubyForge project site[4]. Any feedback from those seeing value and giving it a spin is greatly appreciated.

   Adam Williams

1. Google Code Archive - Long-term storage for Google Code Project Hosting. 2. http://errtheblog.com/post/7708 3. http://rubyforge.org/pipermail/rspec-users/2007-October/003883.html 4. http://faithfulcode.rubyforge.org/svn/plugins/trunk/scenarios/README