| Path: | README |
| Last Update: | Thu Apr 16 05:09:16 -0400 2009 |
FixtureReplacement is a Rails plugin that provides a simple way to quickly populate your test database with model objects without having to manage multiple, brittle fixture files. You can easily set up complex object graphs (with models which reference other models) and add new objects on the fly.
Not only can FixtureReplacement make your test data easier to maintain, it can also help to make your tests and specs much more readable and intention-revealing by allowing you to omit extraneous details and focus only on the attributes that are important for a particular behaviour. It works well with both RSpec and Test::Unit.
See the CHANGELOG.
Most notably, String.random is gone in favor of the method random_string. Call random_string as you would previously in FixtureReplacement:
module FixtureReplacement
attributes_for :user do |u|
u.username = random_string
end
end
To replace calls to String.random in your specs or elsewhere, use the FixtureReplacement module instead:
FixtureReplacement.random_string # or: FR.random_string # FR is a convenience alias for FixtureReplacement
At the heart of FixtureReplacement is the db/example_data.rb file where you define the default attributes for each of your test models. This example shows the default attributes for a user:
module FixtureReplacement
attributes_for :user do |u|
password = random_string
u.value = "a value",
u.other = "other value",
u.another = random_string, # random string 10 characters long
u.one_more = random_string(15), # 15 characters long
u.password = password,
u.password_confirmation = password,
u.associated_object = default_bar # expects attributes_for :bar to be setup
end
end
Note that:
Based on the above definition FixtureReplacement makes the following methods available:
Overrides of specific attributes can be performed as follows:
new_user(:thing => "overridden") create_user(:thing => "overridden")
Overrides can also be used with associations:
scott = create_user(:username => "scott") post = create_post(:user => scott)
In the case that the model has an attr_protected field, FixtureReplacement will assign the field as if it wasn‘t protected, which is convenient for testing:
class User < ActiveRecord::Base
attr_protected :admin_status
end
user = create_user(:username => "scott", :admin_status => true)
user.admin_status # => true
As Dan Manges has outlined in his blog post, "Fixing Fixtures with Factory" (www.dcmanges.com/blog/38), this approach to generating test data has a number of advantages:
The use of random data should also be spoken of. Many may think this to be dangerous, but in fact random data is often helpful. Consider the following snippets of psudo-code (along with it‘s test):
# apps/models/user.rb :
# ----------------------
class User < ActiveRecord::Base
validates_uniqueness_of :username
validates_presence_of :password
after_create :check_password
private
def check_password
# ...
end
public
def establish_friendship_with(other_user)
# ...
end
def friends
# ...
end
end
# The test:
# ---------
def test_make_sure_user_can_establish_friendship
@user_one = User.create({
:username => "foo",
:password => "some password",
:password_confirmation => "some password_confirmation"
})
@user_two = User.create({
:username => "bar",
:password => "some password",
:password_confirmation => "some password confirmation"
})
@user_one.establish_friendship_with(@user_two)
@user_one.friends.should == [@user_two]
end
Notice that the above test adds a lot of extra noise in getting valid users into the database; The test, however, doesn‘t care what the usernames are, that the password is a good one, that the password matches the password confirmation, and so on. The point of the test is not to check those things, but rather that a friendship can be established.
Here would be a similar test with the FixtureReplacement:
# The test:
# ---------
before :each do
@user_one = create_user
@user_two = create_user
end
def test_make_sure_user_can_establish_friendship
@user_one.establish_friendship_with(@user_two)
@user_one.friends.should == [@user_two]
end
Once again, the test above doesn‘t care about usernames, so why should you? But to even store those two users into the database, you will need unique usernames, as well as password which match. Here is where the random data comes in:
# db/example_data.rb
# -------------------
module FixtureReplacement
attributes_for :user do |u|
password = random_string
u.username = random_string
u.password = password
u.password_confirmation = password
end
end
Now, in a different test case, if you do care about the usernames not being random, it is easy to set them:
create_user({
:username => "scott",
:password => "foobar",
:password_confirmation => "foobar"
})
The one major disadvantage behind this approach is that it‘s slow - just as slow as fixtures, if not slower. One approach that the rspec crowd is using is to use this plugin in integration tests, while using mocks & stubs in model unit tests. It‘s not a big deal if your integration tests run slow, since you probably don‘t run them very often.
Another approach is to look to external sources to speed up your test suite:
If you have other ideas for speeding up your test suite, I‘m all ears.
Install the plugin:
git://github.com/smtlaissezfaire/fixturereplacement.git
$ ./script/console Loading development environment >> include FR => Object >> create_user => #<User id: 1, crypted_password: "521faec1c095..." ...>
Add the following to your spec/spec_helper.rb file, in the configuration section:
Spec::Runner.configure do |config|
config.include FixtureReplacement
end
Add the following to your test/test_helper.rb file:
class Test::Unit::TestCase
include FixtureReplacement
end
You will need rspec (version 1.0.8 or later) to run the specs, as well as the sqlite3-ruby gem (and sqlite3 installed):
% sudo gem install rspec % sudo gem install sqlite3-ruby
cd into the fixture_replacement plugin directory:
% cd vendor/plugins/fixture_replacement
Then run with <tt>rake<tt>
% rake
There are also some tests for test/unit. These mainly serve as regressions, but you are free to run them as well.
Specdocs can be found here
The Rcov report can be found here
A flog report can be found here
Thanks to the following for making this software better:
If you would like to change how this software works, please submit a patch with specs through the lighthouse project page:
fixture_replacement.lighthouseapp.com/
This software is dual licensed under the MIT and the GPLv3 Licenses (it‘s your pick).
Copyright 2007-2009 Scott Taylor <scott@railsnewbie.com>