views:

2261

answers:

9

There are a dozen Rails plugins whose goal is to replace fixtures in testing. Here are a few I can think of:

  • fixture replacement
  • factory girl
  • factories and workers
  • rails scenarios
  • fixture-scenarios
  • object daddy

There are probably others. Which of these plugins do you prefer and why?

+5  A: 

I personally use Faker with a custom Factory class. This allows me to create my factories, and populate the generated instances with non-static data.

# spec/factory.rb
module Factory
  def self.create_offer(options={})
    Offer.create({
      :code => Faker::Lorem.words(1),
      :expires_on => Time.now + (rand(30) + 1).day
    }.merge(options))
  end
end


# spec_helper.rb
require 'faker'
require 'spec/factory'


# In the specs
@offer = Factory.create_offer(:code => 'TESTING')
Mr. Matt
+3  A: 

+1 factory girl

Mike Breen
voted up for "girl"
DFectuoso
+3  A: 

We've just started using Factory Girl for our projects. Its way of doing things wasn't very different from our home grown solution so its working well for us.

Jeff Waltzer
+4  A: 

I'll advocate for Fixture Replacement 2. Your default (don't care) model attributes are stored all in one place, db/example_data.rb, and provide quick valid objects. Any attributes you specify upon creation override the default attributes - meaning the data that you care about is in the test, and nothing else.

Your example data can also refer to other default models, which are represented by procs with delayed evaluation, so you can override associations easily when desired.

Version 2 provides a much cleaner definition format, while still providing the magic new_*, create_*, and default_* methods for every model.

I would avoid any kind of "scenarios" scheme which encourages building more and more test data that's hard to read later. You can create named(custom) objects with FR2, but I've never found a need for it.

P.S. Make sure you consider your unit testing strategy as well - Fixtures and all their analogues are real objects that hit the DB, making for functional or integration tests. I'm currently using RSpec's mocking along with stub_model() and the latest unit_record gem to disallow DB access.

James Baker
+3  A: 

I use Faker along with Populator gem by Ryan Bates. He even has a nice screencast at http://railscasts.com/episodes/126-populating-a-database.

Subbu
+2  A: 

I've been playing around with machinist lately and am digging it.

Mike Breen
+3  A: 

I'm a big fan of the factory when you only need one or a few objects. You can either write your own or use Thoughtbot's Factory Girl.

For situations where you need a curated set of interrelated objects, fixtures beat factory, and you should take a look at the excellent Lite Fixtures which makes fixtures considerably more DRY and manageable.

Abie
A: 

Factory Girl is great. We use it in work loads.

Factory.define :usa, :class => Team do |f|
  f.country_name 'USA'
  f.rank         15.6
end

Factory.define :player do |f|
  f.first_name 'Stevie'
  f.last_name  'Wonder'
  f.team       Factory.build(:usa)
end

Then in your specs you can use Factory.build(:usa) or Factory.create(:usa) to build or create a USA team respectively.

James Conroy-Finn
+2  A: 

I can give Factory Girl a plus one as well. The way it can associate between multiple Factories is really helpful when you have a somewhat normal model set. A Project has one project manager, for example.

Factory.define :project_manager do |f|
  f.first_name "John"
  f.last_name  "Doe"
end

Factory.define :project do |f|
  f.name "Sample Project"
  f.association :project_manager
end

That way you don't need to worry about actually setting up the relationships in each test. It can also do some work like Faker where you can build sample data in factories using Factory.sequence. For all the information on Factory Girl, check out: http://dev.thoughtbot.com/factory_girl/.

Kyle Daigle