Test Seeds allow efficient usage of object factories (like Factory Girl) in tests. Instead of creating objects for similar scenarios in each test case, Test Seeds start a db transaction for each test file, create all the common objects once, and then uses db savepoints for each test case allowing for the common objects to be re-used.
Fixtures are a great way to get started. However, as your application becomes more complex, fixtures become a nightmare to manage and maintain. To alleviate this problem, people have flocked to object factories which allow creating complex testing scenarios right next to the code that tests those scenarios. Often similar scenarios are needed for a set of tests and the following pattern emerges,
class TestSomething < ActiveSupport::TestCase setup :create_scenario def create_scenario @object_1 = ...create AR objects... @object_2 = ...create AR objects... @object_3 = ...create AR objects... end def test_case_1 end ... def test_case_N end end
Sometimes creating the scenario in the setup callback, create_scenario is called by tests directly as needed. Either way, the problem is that create_scenario is called multiple times and creating objects via ActiveRecord is very slow. Test Seeds addresses this problem.
Transactional fixtures work as follows,
test file do load fixtures transaction do test case 1 end transaction do test case 2 end transaction do test case 3 end end
Test Seeds piggy backs on the transaction fixtures functionality. Test Seeds load fixtures into the database in the same way but then start a db transaction for the duration of the test file. Any objects for the common scenarios are then created and inserted into the database. Test Seeds then execute each test case within a context of a db savepoint (or nested db transactions). This allows test seeds to be inserted into the database once and then re-used for each test case that needs it. Here is the pseudo code,
test file do load fixtures transaction do load seeds savepoint do test case 1 end savepoint do test case 2 end savepoint do test case 3 end end end
There are two main ways of using Test Seeds. The first way makes all the seeds available to all the tests,
class TestSomething < ActiveSupport::TestCase include TestSeeds seeds do @object_1 = ...create AR objects... @object_2 = ...create AR objects... @object_3 = ...create AR objects... end def test_case_1 # @object_1, @object_2, and @object_3 are available here end ... def test_case_N # @object_1, @object_2, and @object_3 are available here end end
Alternatively, you can be more selective which seeds go with which test cases,
class TestSomething < ActiveSupport::TestCase include TestSeeds seeds(:scenario_a) do @object_a1 = ...create AR objects... @object_a2 = ...create AR objects... @object_a3 = ...create AR objects... end seeds(:scenario_b) do @object_b1 = ...create AR objects... @object_b2 = ...create AR objects... @object_b3 = ...create AR objects... end def test_case_1 setup_seeds(:scenario_a) # @object_a1, @object_a2, and @object_a3 are available here end def test_case_2 setup_seeds(:scenario_b) # @object_b1, @object_b2, and @object_b3 are available here end def test_case_3 setup_seeds(:scenario_a, :scenario_b) # @object_a1, @object_a2, and @object_a3 are available here # @object_b1, @object_b2, and @object_b3 are available here end end
-
Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet
-
Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it
-
Fork the project
-
Start a feature/bugfix branch
-
Commit and push until you are happy with your contribution
-
Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
Copyright © 2011 Paul Kmiec. See LICENSE.txt for further details.