Factory_boy aims to avoid slow unit tests due to usage of create/find fixtures in database, with factory_girl for example. Factory_boy can be used as factory_girl except that factories are not created in database. ActiveRecord::Base find method is stubbed to return fixtures (plants) you have instanciate. Differenciate find :all, :first, :last, but doesn’t do the work of find with sql conditions. Anyway we don’t think it’s important for unit test, if some find calls with sql conditions, :include … etc have to be tested, report it in integration tests is a better idea.
See some examples below. You can see also unit tests / code for deeper comprehension.
gem install factory_boy
Define your Plants (=~ Factories if factory_girl) in test/plants.rb
Example :
Plant.define :user do |user| user.name="Bart" user.age=800 end
Get it with :
user = Plant(:user)
Example of tests :
def test___1 user = Plant(:user) assert_equal user, User.find #OK assert_equal user, User.find(:first) #OK assert_equal user, User.find(:last) #OK end def test___2 2.times { Plant(:user) } assert_equal 2, User.find(:all).size #OK end
You can also create a particular plant of user like that:
user = Plant(:user, :name => "Marie", :age => age)
Plant.define :admin, :class => User do |user| user.name = "Bart" user.age = 800 end
Assign fixtures to association in definition of plant :
Plant.define :profile do |profile| profile.password = "BREIZH!" end Plant.define :adress do |adress| adress.number = 12 adress.street = "rue de Brest" end Plant.define :user do |user| user.name = "Bart" user.age = 800 user.profile = Plant.association(:profile) user.adresses = [Plant.association(:adress)] end
If you want to use the value of another attribute in definition, do like that :
Plant.define :user do |user| user.name = "Marie" user.adresses = [Adress.new(:street => "Rue de #{user.name}")] end
As with factory_girl you are able to use sequences, like that :
Plant.sequence :email do |n| "incognito#{n}@kantena.com" end Plant.next(:email) # => "incognito1@kantena.com" Plant.next(:email) # => "incognito2@kantena.com"
No dependency. Doesn’t work, for now, with Active Support 3.0 (In development)
-
Stubs only find of Plant class so we can use both AR find on klasses that are not ‘planted’
-
Plant(:xx).clear
-
Provide an id to each Plant
-
When assign instance to an association(ie profile of user), set foreign_key id (ie profile_id of user)
-
To work with Rails 3 (Active Support 3)
-
Stub find with conditions using Arel( for Rails 3)
-
FIX : Push new object in pool of a class doesn’t override objects in pool. Safe push.
-
FIX : Use #clone instead of #dup. Not same behavior with and without rails(may be overriden by active support)
-
FIX : Bug with override TestCase#run under ActiveSupport::TestCase
Report Bugs here , on github