home icon contact icon rss icon

Textmode

tools I use

Factory Girl - Rails fixture replacement

I think you all know that, when using fixtures in your test, you keep switching between files to see what fixtures there are, always struggling with dependencies and conflicts.

There are a couple of helpers that solve this, but this is the best one I came across until know: Factory Girl

As the names says, it provides some kind of factory for your objects and instances.

The following snippet illustrates the definition of such a factory:


# define an incremental username
Factory.sequence :user do |n|
  "user#{n}" 
end

# define a user factory
Factory.define :user do |u|
  u.admin      false
  u.username { Factory.next(:user) } # lazy loaded
end

# define a project factory with associated user
Factory.define :project do |p|
  p.title 'myproject'
  p.creator   {|a| a.association(:user) } # again lazy loaded
end

Now, this factory can be used in your tests:


it "should do something" do
  Factory.create(:user) # creates a user
  Factory(:user) # creates another user (note the shortcut)
  @u = Factory.build(:user, :username => 'customuser') # only build, no save
  Factory.create (:project, :creator => @u)
end

I think you get the basic idea behind it, it’s actually pretty clean and makes tests a lot more readable without looking at fixtures.

Note: At the time of this writing, the attribute name does not work since there is a conflict (that will be resolved soon). Instead you have to use:


Factory.define :project do |p|
  p.add_attribute :name, "myname" 
end


Umuro said

Jun 25, 2009 @ 04:45 PM

And moreover, in addition to that, we can enhance factories with their own helper methods. To design clean and complicated factories – http://conceptspace.wikidot.com/blog:39

Factory.define :child do |f| end

class << f
    #do whatever you can do in a normal class definition
    def default_parent
        @default_parent ||= Factory(:parent)
    end
end
f.sequence(:name) {|n| "Child#{n}"}
f.parent_id { f.default_parent.id }

RSS feed for comments on this post

Leave a Comment