At the Forge - Fixtures and Factories

Use factories and fixtures in your Rails applications to help simplify your database-related testing.

instead, I can say this:

  person: one
  meeting: one

  person: two
  meeting: two

Obviously, you would want to choose more descriptive names for your fixtures. But, I now have indicated that meeting #1 is with person #1, and meeting #2 is with person #2. This is obviously more descriptive than the simple numbers would be.

You can even do one better than this, because fixtures understand the has_many :through associations that I defined in the models. Just as in the Ruby code, I can add a person to a meeting with:

meeting.people << a_person

I can put the same sorts of information in the fixture file. For example:

  starting_at: 2009-05-10 00:48:12
  ending_at: 2009-05-10 01:48:12
  location: MyText
  people: one, two
  starting_at: 2009-05-10 00:48:12
  ending_at: 2009-05-10 01:48:12
  location: MyText
  people: two

If you do things this way, you don't want to define things in both the meeting_people fixture and in the meetings fixture. Otherwise, you might be in for some very strange errors. Note that fixture files are ERb (embedded Ruby) files, so you can have dynamically generated entries, such as:

  starting_at: <%= 5.minutes.ago %>
  ending_at: <%= %>
  location: MyText
  people: one, two

Now, how do you use these fixtures in your tests? It's actually pretty straightforward. You need to load the fixtures you want with the fixtures method:

fixtures :meetings

By default, all fixtures are imported, thanks to:

fixtures :all

in test/test_helper.rb, which is imported automatically into all tests. Then, in your test, you can say something like this:

get :edit, :id => people(:one).id

This example (of a functional test) will load the person object identified as one in people.yml, invoking the edit method and passing it the ID of the appropriate fixture.

Factory Girl

For a small site, or when you can keep everything in your head, fixtures are just fine. I've certainly used them over the years, and I've found them to be an invaluable part of my testing strategy. But, factories are an alternative to fixtures that have become increasingly popular, both because they're written in Ruby code, and they allow you to do all sorts of things that are difficult or impossible with YAML fixtures.

Factory Girl is one of the best known factories, written and distributed by the Thoughtbot company, and it is available as a Ruby gem. After installing Factory Girl on your system and bringing it into your application's environment with:

config.gem "thoughtbot-factory_girl",
             :lib    => "factory_girl",
             :source => ""

in config/environment.rb, you will be able to use it. Basically, Factory Girl allows you to create objects in Ruby, rather than load them from fixture files. No defaults are created for you by the generator, but that's not a big deal, given how easy it is to use Factory Girl to create test objects.

Above, I showed how in a test environment using fixtures, you can grab the person object with a name of one by using the people method, and then passing a symbol:

get :edit, :id => people(:one).id

people(:one) is a full-fledged ActiveRecord object, with everything you might expect from such an object. Factory Girl works in a different way. First, you need to create a test/factories.rb file, in which your factories are defined. (You also may create a test/factories/ directory, the contents of which will be Ruby files defining factories.)

To create a factory for people (that is, in place of people.yml), insert people.rb inside test/factories:

Factory.define :person do |p|
  p.first_name 'Reuven'
  p.last_name  'Lerner' ''

Now, inside the tests, you can say:

get :edit, :id =>


person =
get :edit, :id =>

At first glance, this doesn't seem too exciting. After all, you could have done roughly the same thing with your fixture, right? But factories allow you to override the defaults:

person =, :first_name => 'Foobar')
get :edit, :id =>

But wait, there's more. You can set associations as follows:

Factory.define :person do |p|
  p.first_name 'Reuven'
  p.last_name  'Lerner' ''
  p.meetings {|meetings| meetings.association(:meeting)}

In other words, if you have created a meeting factory, you can incorporate it into your person factory, taking advantage of the association, using a fairly natural syntax.

An even more interesting idea is that of sequences. If your application needs to create a large number of test people, you might want each of those people to have a unique e-mail address. (Never mind that the e-mail never will be sent.) You can do this with a sequence:

Factory.define :person do |p|
  p.first_name 'Reuven'
  p.last_name  'Lerner'
  p.sequence(:email) {|n| "person#{n}" }

The first person created with this factory will have an e-mail address of; the second will be and so forth.

As you can see, Factory Girl is as easy to use as YAML fixtures, but it offers a great many capabilities that come in handy when testing Rails applications.

Factory Girl is a terrific library for factories, and it has become quite popular since it was first released. But, not everyone liked its basic syntax, and one of those people was Pete Yandell, who decided that although the basic idea behind factories was sound, he wanted to use a different (and more compact) syntax for his factories. Thus was born Machinist, which uses a Sham object to describe fields in an object, which are then assembled into blueprints for specific objects. For example:

require 'faker'

# Define the fields that we will need
Sham.first_name  { Faker::Name.first_name }
Sham.last_name  { Faker::Name.last_name } { }

# Now use these field definitions to create a blueprint
Person.blueprint do

Now you can use these blueprints to create test objects. For example:

person = Person.make()

As with Factory Girl, you also can override the defaults:

person = Person.make(:email => '')


Geek Guide
The DevOps Toolbox

Tools and Technologies for Scale and Reliability
by Linux Journal Editor Bill Childers

Get your free copy today

Sponsored by IBM

Upcoming Webinar
8 Signs You're Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
11am CDT, April 29th
Moderated by Linux Journal Contributor Mike Diehl

Sign up now

Sponsored by Skybot