Factory Girl for Rails can do more...

Blog ยป Factory Girl for Rails can do more…

Posted on 25 Jun 2009 13:31

Ignore this whole article. Lastest versions of FactoryGirl are capable without tricks. Just go for the latest…


icon-factorygirl.png

Unit testing with FactoryGirl is very DRY. The power of Ruby enables you to do more cool and elaborate things with factories. Factories can be equipped with useful custom methods. Let's define a child factory that always uses the same default parent:


Update: Factory girl implementation has greatly changed since the writing of this article. So here is how it would be in FactoryGirl 4.0.0 . I'll convert the whole article as soon as I have time :

factory :child do
    sequence(:name) {|n| "Child#{n}"}
 
    class << @definition
      def default_parent
      @default_parent ||= FactoryGirl.build(:parent)
      end
    end
 
    parent_id { @definition.default_parent.id }
end

(This is the outdated syntax)

Factory.define :child do |f|
    f.sequence(:name) {|n| "Child#{n}"}
 
    def f.default_parent
        @default_parent ||= Factory(:parent)
    end
 
    f.parent_id { f.default_parent.id }
end

Now every child created will have the same default parent. Instead of abusing the global space, instead of having to modify class Factory, the method and variable its using is neatly included in the factory instance.

And whenever you want, you can use another parent in the tests.

child = Factory(:child, :parent_id=another_parent.id)

But the default child will come with the single default parent. More speed and space

child1 = Factory(:child)
child2 = Factory(:child)
# child1.parent == child2.parent

You can access the custom method elsewhere

f =  Factory.factory_by_name(:child)
f.default_parent

As you see, you can treat the factories like classes - with custom methods and properties. This allows possibilities which are not evident from the syntax of Thoughtbot Factory Girl

Remember. In Ruby, object instances can have their custom methods!

To be able to do whatever you can do in a normal class declaration, here is an alternative syntax:

Factory.define :child do |f|
 
    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 }
end

Thoughtbot Factory Girl will allow you write your tests easier than using fixtures.

Happy unit testing… Don't forget to use Shoulda!

If you like this page, please spread the word: diggdel.icio.usFacebook

You can contact me if you have questions or corrections.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License