kylejginavan / factory_data_preloader

Preload data created by factory girl (or any other Rails fixtures alternative) so that you can use Rails' built-in test transactions.
https://github.com/myronmarston/factory_data_preloader
33 stars 3 forks source link

= 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|

note the use of the :depends_on option to force the users to be loaded first.

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|

note the use of the :model_class option when the model class cannot be inferred from the symbol.

data.add(:another_post) { Post.create(:user => FactoryData.users(:john), :title => 'Life is good') }

end

FactoryData.preload(:comments, :depends_on => [:users, :posts]) do |data|

:depends_on lets you pass an array

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:

test/user_test.rb

class UserTest < ActiveSupport::TestCase def test_thom_has_last_name user = FactoryData.users(:thom) assert_equal 'York', user.last_name end end

test/post_test.rb

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:

in test_helper.rb

FactoryDataPreloader.preload_all = false

test/user_test.rb

class UserTest < ActiveSupport::TestCase preload_factory_data :users # multiple types can be listed as necessary

tests go here...

end

test/post_test.rb

class PostTest < ActiveSupport::TestCase preload_factory_data :posts # dependencies are taken into account, so users will automatically be preloaded as well.

tests go here...

end

== Notes, etc.

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.