= factory_data_preloader
If you're like me, you really dislike using rails test fixtures. On the rails projects I've worked on that have used test fixtures, we've had a number of tests that passed as false positives because the test fixtures don't represent "real data". Fixtures just dump the data you've defined directly into the database, without going through the model--meaning you don't get any of the validations or before/after save callback behavior defined on your models.
There are multiple gems and plugins that address this; my personal favorite is {factory girl}[http://github.com/thoughtbot/factory_girl/].
However, none of the solutions I've tried are as fast as using test fixtures. When you use test fixtures,
rails rolls back the database transaction used in each test and allows you to re-use your fixture data.
This is much much quicker then creating the data you will use directly in each test.
This gem attempts to solve this issue, and give you the best of both worlds: create your test data using factory girl, the models themselves, or any other solution you want, while also being able to pre-load it and re-use it in each test when rails rolls back the transaction.
== Download
Github: http://github.com/myronmarston/factory_data_preloader
Gem: gem install factory_data_preloader --source http://gemcutter.org
== Usage
Load the gem using Rails' 2.1+ gem support, in either config/environment.rb, or config/environments/test.rb: config.gem 'factory_data_preloader', :source => 'http://gemcutter.org'
Define your preloaded data. FactoryData will automatically require test/factory_data.rb or test/factory_data/*.rb. Define your data in these files like this:
FactoryData.preload(:users) do |data| data.add(:thom) { User.create(:first_name => 'Thom', :last_name => 'York') } data.add(:john) { User.create(:first_name => 'John', :last_name => 'Doe') } end
FactoryData.preload(:posts, :depends_on => :users) do |data|
data.add(:tour) { FactoryData.users(:thom).posts.create(:title => 'Tour!', :body => 'Radiohead will tour soon.') }
end
FactoryData.preload(:some_other_posts, :model_class => Post, :depends_on => :users) do |data|
data.add(:another_post) { Post.create(:user => FactoryData.users(:john), :title => 'Life is good') }
end
FactoryData.preload(:comments, :depends_on => [:users, :posts]) do |data|
data.add(:woohoo) { FactoryData.users(:john).comments.create(:post => FactoryData.posts(:tour), :comment => "I can't wait!") }
end
Finally, use this preloaded data in your tests:
class UserTest < ActiveSupport::TestCase def test_thom_has_last_name user = FactoryData.users(:thom) assert_equal 'York', user.last_name end end
class PostTest < ActiveSupport::TestCase def test_post_has_body post = FactoryData.posts(:tour) assert_not_nil post.body end end
All factory data is automatically preloaded for all tests. In a large rails application, this can incur a significant performance penalty at the start of each test run. If you want finer grain control over which preloaders run, you can configure it like so:
FactoryDataPreloader.preload_all = false
class UserTest < ActiveSupport::TestCase preload_factory_data :users # multiple types can be listed as necessary
end
class PostTest < ActiveSupport::TestCase preload_factory_data :posts # dependencies are taken into account, so users will automatically be preloaded as well.
end
== Notes, etc.
The syntax used before the 0.5.0 release is still allowed but has been deprecated. Instead of this:
FactoryData.preload(:users) do |data| data[:thom] = User.create(:first_name => 'Thom', :last_name => 'York') data[:john] = User.create(:first_name => 'John', :last_name => 'Doe') end
Use this:
FactoryData.preload(:users) do |data|
data.add(:thom) { User.create(:first_name => 'Thom', :last_name => 'York') }
data.add(:john) { User.create(:first_name => 'John', :last_name => 'Doe') }
end
== Known Issues
== Copyright
Copyright (c) 2009 Myron Marston, Kashless.org. See LICENSE for details.