Fixie is a library for creating test databases in Rails. It supplements db:test:prepare to populate the test DB from Ruby fixture files.
Fixie uses ActiveRecord to populate the test database, but it also gives re-usable IDs to the records you create so you can easily refer to them in tests. (These IDs are created with Fixtures.identify, so they are the same IDs used by Rails fixtures.)
Fixtures suck because they are difficult to maintain and don't validate the records that are inserted.
Factories provide a nice solution to the validation problem, but make it difficult to set up a complicated object graph.
I've developed ad hoc test database pre-population scripts that allow creation of complicated object graphs, but make it difficult to pull out specific records because unlike fixtures or factories, you don't have an easy to use identifier.
Fixie allows you to pre-populate your database with example data that is validated by ActiveRecord, yet can easily be retrieved in tests.
It is also compatible with the use of factories, so you can lay down a base layer of objects and then build specific objects for tests as needed.
In the test/fixie directory, create an *.rb file to populate the database:
Foobar.fixie(:record_name, :name => "my record", :email => "firstname.lastname@example.org")
Records created in this way are returned for use later in the population script:
admin = Role.fixie(:admin, :name => 'admin') sam = Person.fixie(:sam, :name => "Sam Smith", :email => "email@example.com") sam.roles << admin
If you have a belongs_to association, you can also associate objects like this:
schwinn = Manufacturer.fixie(:schwinn, :name => 'Schwinn Bicycle Company', :founded => 1895) continental = Bicycle.fixie(:continental, :name => 'Continental', :speeds => 10, :brakes => true, :manufacturer => schwinn)
This works because Fixie sends attr= to the object being created, so ActiveRecord associates the parent object with the child.
Invalid records will raise an exception and your tests will not run.
You may have as may fixie files as you like, so organize the test data however it makes sense.
In tests, you can look up that record like this:
@sam = Fixie.people(:sam)
If the object with that record ID doesn't exist, an exception will be raised.
Your test database will be populated with records before the tests run. This is accomplished by appending to the db:test:prepare task and inserting the records into the test database by loading the fixie files.
That's about all there is to it, but you can check out the examples directory for a closer look at how to use Fixie.
NOTE: creating a test database in NOT compatible with using fixtures (at least not for the same tables), because loading fixtures deletes all existing records.
GENERATOR NOTE: If you do happen create a model via a rails generator, you'll get a file in the text/fixtures directory which will override any Fixie you've set up. So you'll need to remove that file for Fixie to work.
This is a work in progress. I am currently using Fixie as I feel it's better than the ad hoc scripts I used before, but I am eager to hear your suggestions on how to improve this library.
Some ideas I have:
allow use of the fixture or fixture-style methods (like bicycles(:foobar))
change the lookup method to be ClassName.fixie(:record_name)
don't polute ActiveRecord::Base with the fixie method except in tests?
Copyright © 2009 Luke Francl, released under the MIT license.