0.0
Low commit activity in last 3 years
Fast and easy to maintain fixtures inside factories
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

fixture_bot

Improve the performance of your tests, as factories generate and insert data into the database every time, it can be slow. See benchmarks.

Problems using Rails fixtures:

  • No data validation
  • Long loading of fixtures (for one or all tests - equally long)
  • YML format (no reuse code)
  • heavy support for fixtures and factories together

Installation

group :test do
  gem "factory_bot"
  gem "fixture_bot", require: false
end

Usage

To define your fixture in factories, use the preload method

FactoryBot.define do
  factory :user do
    name "John Doe"
    sequence(:email) {|n| "john#{n}@example.org" }
  end
  
  preload(:users) do
    fixture_with_id(:first) { create(:user, id: 1) }
    fixture(:john) { create(:user) }
    fixture(:with_gmail) { create(:user, email: "email@gmail.com") }
  end
end
FactoryBot.define do
  factory :projects do
    name "My Project"
    user { users(:with_gmail) }
  end

  preload(:users) do
    fixture(:myapp) { create(:project, user: users(:john)) }
  end
end

RSpec usage

require "spec_helper"

describe User do
  let(:user) { users(:john) }

  it "returns john's record" do
    expect(users(:john)).to be_a User
  end

  it "returns myapp's record" do
    expect(projects(:myapp).user).to eq users(:john)
  end

  it "each call fixture return new object" do
    expect(user.object_id).not_to eq users(:john).object_id
  end
end

RSpec Setup

On your spec/support/factory_bot.rb file

require "fixture_bot" # the order is important, it must be before loaded factories
require "factory_bot_rails"

FactoryBot::SyntaxRunner.class_eval do
  include RSpec::Mocks::ExampleMethods
end

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

Minitest Setup

On your test/test_helper.rb file, make sure that transaction fixtures are enabled. Here's what your file may look like

# First, load fixture_bot
require "fixture_bot"
FixtureBot.minitest
require "test_helper"

class UserTest < ActiveSupport::TestCase
  test "returns john's record" do
    assert_instance_of User, users(:john)
  end

  test "returns myapp's record" do
    assert_equal users(:john), projects(:myapp).user
  end
end

Callbacks

FixtureBot.after_load_fixtures do
  # code uses fixtures
end

Benchmarks

factories vs fixtures

# simple model with 10 fields
Benchmark.ips do |x|
  x.report("fixture") { brands(:lux) }.   # fixture:  4666.2 i/s
  x.report("factory") { create(:brand) }  # factory:  1077.8 i/s - 4.33x  slower
  x.compare!
end

# user model with 40+ fields, 1 association
Benchmark.ips do |x|
  x.report("fixture") { users(:with_post_index)} # fixture:  3395.4 i/s
  x.report("factory") { create(:user) }          # factory:   159.6 i/s - 21.27x  slower
  x.compare!
end

# product model with 40+ fields, 5+ associations
Benchmark.ips do |x|
  x.report("fixture") { products(:available) }         # fixture:  3564.3 i/s
  x.report("factory") { create(:product, :available) } # factory:    67.7 i/s - 52.68x  slower
  x.compare!
end

License

The gem is available as open source under the terms of the MIT License.