Use FactoryGirl in Rails

FactoryGirl is a gem aimed at replacing Fixtures. If you wonder that, take a look at what's wrong with fixtures.

1. Add factory_girl_rails to your Gemfile

group :test, :development do
    gem 'factory_girl_rails'
end

2. Add to your spec/rails_helper config block:

RSpec.configure do |config|
  #  Other config code
  config.include FactoryGirl::Syntax::Methods  # Add this line
end

3. Define factory

In spec/factories.rb or test/factories.rb

FactoryGirl.define do
    factory :user do
        username ‘foo’
        password ‘secret’
        email {“#{username}@example.com”} # define value dynamically, pass a block
    end
end

4. Use the factory in your spec

user = create(:user)
user = create(:user, username: ‘xiaochuang’, password: ‘xiaochuangchuang’)  # Override the default value.
user = build(:user)  # Will not save to database, faster than create

5. tips and tricks

1. use sequence in model field

Say your user model has a validation of uniqueness for the attribute username, then if you call create(:user) multiple times without passing in the username, you’ll get an error. In this case, you can use sequence to auto generate username for you.

factory :user do
    sequence(:username) {|n| “user#{n}”}
end

Now everytime you create(:user) will return a user with a different username in the form: user0, user1, user2...

2. Use associations

Assume you have a Post model that references to a User.

factory :user do
    username ‘xiaochuang’
    password ‘xiaochuangchuang’
end

factory :post do
    title ‘A new post’
    user #Yes, it’s just that simple.
end

However, the above usage assume that the user field is name user, if not, you can use association to customize the behavior. association :author, factory: :user, username: ‘xiaochuang’

3. Nested factory

Say your user model have an attribute called admin, this is used frequently and you don’t want to pass in the admin attribute very time. In this case, you can use a nested factory:

factory :user do
    username ‘xiaochuang’
    password ‘xiaochuangchuang’
    admin false

    factory :admin do
        admin true
    end
end

In your spec, you can just create(:admin) to create a user that set the admin to true.

4. Use build instead of create if possible.

By using create(:model), you create the model instance and save if to the database. In many cases if you don’t have to save it the the database, you can use build(:model). This will build an instance but wouldn’t save to the database, which makes it a little bit faster.
And also, in many cases you if you can just Model.new, you can bypass factories at all, which is even faster.