-
Notifications
You must be signed in to change notification settings - Fork 2
Scenarios has been deprecated. Please use Dataset instead.
License
aiwilliams/scenarios
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
= Deprecated -- Use Dataset Scenarios has been replaced by Dataset, a complete rewrite, test driven. It has a number of bugs fixed and more features. Check out http://github.com/aiwilliams/dataset. I hope you find it far more useful and worth helping to extend. == Rails Scenarios Plugin Who hasn't experienced the pain of dozens of YAML files filled with hundreds of inter-related data structures? When do you look at People of an Organization and not have to look at the organization_id, open the organizations.yml file, and search for 'id: X'? In a nutshell, scenarios are a drop in replacement for YAML fixtures. Instead of encouraging you to create a mindless amount of raw data in the form of YAML, scenarios encourage you to create code that populates your tables with the appropriate records. How is it different from other solutions? A few things: * It continues to provide a fundamental, fast insertion method using attributes written directly to a table. This is the Scenarios::TableMethods#create_record method. * It allows you to create records using validations if you prefer, or if it's important to have all your callbacks be invoked. See Scenarios::TableMethods#create_model. Both create_record and create_model allow you to name your instances for retrieval by the instance and id reader methods (more below). * Nothing stops you from simply invoking YouModel.create!, etc. We'll still keep track of the tables the scenario modifies and clean things up afterward. * It allows you to create re-usable scenarios as classes. These classes are like any other class - they may include modules, subclass, and be composed of other scenarios. See Scenarios::Base.uses. This also means that you can load any scenario into any Rails environment. That's what the 'rake db:scenario:load' task is good for (more below). Very handy for re-using all that test support code to create populated demos! === Quick Start Since Scenarios is a Rails plugin at this time, you should get it installed, using the appropriate method (script/plugin, svn, piston) into your vendor/plugins directory. Once you have this, in your spec_helper.rb or test_helper.rb, add the following line after the spec requires: require 'scenarios' The Scenarios you write should be placed in the spec/scenarios directory of your Rails project if you're using RSpec, or the test/scenarios directory of your Rails project if you're using Test::Unit. Scenario file names always end in "_scenario.rb" and classes end in "Scenario". A simple scenario looks like this: # in spec/scenarios/users_scenario.rb or test/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 In the example above, I'm using the <tt>create_record</tt> instance method to create two users: John and Cindy. Notice the calls to <tt>create_record</tt>. There are three parameters. The first is the singular name of the table to insert the record into, the second is the symbolic name of the record (more on that later), and the third is a hash of the attributes of the record. To use the UsersScenario in a description, you should declare it using the <tt>scenario</tt> method. Here it is within a spec file (RSpec): # 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 and here it is within a standard Test::Unit test: # in test/unit/user_test.rb class UserTest < Test::Unit::TestCase scenario :users def test_do_something user = users(:john) assert_equal "doodaht", user.password end end Notice that it is easy to load an instance of a model object using its symbolic name with a reader method, similar to that of Rails' fixtures. In the example above, I loaded John with the reader method <tt>users</tt> and the symbolic name <tt>:john</tt>. (Remember that in the Users scenario I declared that John should be accessible through the symbolic name <tt>:john</tt>.) I could also have retrieved an array of user fixtures by passing in multiple symbolic names to the reader method: # in spec/models/user_spec.rb describe User do scenario :users it "should allow me to get all admins" do admins = users(:john, :ryan) User.admins.should eql(admins) end end === Composition 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 or test/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/scenarios/comments_scenario.rb or test/scenarios/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 In the example above, the CommentsScenario declares that it depends on the Posts scenario with the <tt>uses</tt> class method. This means that if you load the CommentsScenario, the PostsScenario will be loaded first and the CommentsScenario will have access to all the data loaded by the PostsScenario in its own <tt>load</tt> method. Note that inside the load method I'm using another form of reader methed which simply gives you the id for a symbolic name (in this case: <tt>post_id</tt>). This is most useful for making associations, as done here with comments and posts. === Helper Methods Another way of simplifying your scenarios and specs/tests is through helper methods. The Scenarios plugin provides a handy way to declare helper methods that are accessible from inside the scenario and also from inside related RSpec/Test::Unit examples: # in spec/scenarios/users_scenario.rb or test/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 Helper methods declared inside the helpers block are mixed into the scenario when it is instantiated and mixed into examples that declare that they are using the scenario. Also, in the case where one scenario <tt>uses</tt> another, the using scenario will have the helper methods of the used scenario. # 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 # in test/functional/projects_controller_test.rb class PeopleControllerTest < Test::Unit::TestCase scenario :users def test_index login_as(users(:john)) get :projects assert_tag('#active_projects') end end Notice that within my specs/tests I have access to the login_as helper method declared inside the <tt>helpers</tt> block of the UsersScenario. Scenario helpers are a great way to share helper methods between specs/tests that use a specific scenario. === Built-in Scenario There is a scenario named 'blank' that comes with the plugin. This scenario is useful when you want to express, and guarantee, that the database is empty. It works by using your db/schema.rb, so if the table isn't created in there, it won't be cleaned up. Scenario.load_paths is an array of the locations to look for scenario definitions. The built-in scenarios directory is consulted last, so if you'd like to re-define, for instance, the 'blank' scenario, simply create 'blank_scenario.rb' in your spec/scenarios or test/scenarios directory. === Load Rake Task The Scenarios plugin provides a single Rake task, <tt>db:scenario:load</tt>, which you may use in a fashion similar to Rails fixtures' <tt>db:fixtures:load</tt>. rake db:scenario:load SCENARIO=comments When invoked, this task will populate the development database with the named scenario. If you do not specify SCENARIO, the task will expect to find a default scenario (a file 'default_scenario.rb' having DefaultScenario defined in it). It is our practice to have it such that this scenario <tt>uses</tt> a number of our other scenarios, thereby: * encouraging us to use test data that looks good in the running development application * allowing us to troubleshoot failing tests in the running development application === More Information For more information, be sure to look through the documentation over at RubyForge: * http://faithfulcode.rubyforge.org/docs/scenarios You might also enjoy taking a look at the specs for the plugin and the example scenarios: * http://faithfulcode.rubyforge.org/svn/plugins/trunk/scenarios/spec/scenarios_spec.rb * http://faithfulcode.rubyforge.org/svn/plugins/trunk/scenarios/spec/scenarios Browse the complete source code: * http://faithfulcode.rubyforge.org/svn/plugins/trunk/scenarios === Running Tests You should be able to simply run rake. Notice in testing/environment.rb the revisions under which this project will work. If you intend to test against HEAD, you will need to delete the directory testing/tmp/trunk/HEAD. At some point, it would be nice to have the script track the revision of HEAD that we have, and update the directory automatically. === License The Scenarios plugin is released under the MIT-License and is Copyright (c) 2007, Adam Williams and John W. Long. Special thanks to Chris Redinger for his part in helping us get this plugin ready for the public.
About
Scenarios has been deprecated. Please use Dataset instead.
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published