Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

  • Blog Navigation
Fixture builder and rspec-acceptance

Getting rspec-acceptance (webdriver, no cucumber) to work correctly with fixture_builder and database_cleaner can be a bit of a drag.

It is actually not that hard and there are resources all over the inter tubes, you just have to find them.
For the sake of saving myself and some fellow programmers some time I will summarize the process we followed.

First, you need to make sure to have the fixture_builder, database_cleaner and while we’re at it headless gems installed.
Then the bulk of the work happens in acceptance_helper.rb, spec_helper.rb and fixture_builder.rb.

Details on what is in them are below. There are some notable things which I mention in context with the code.


If you need you fixtures loaded in a particular order
you can load them in that order by specifying them as argument for the config.global_fixtures variable in spec_helper.

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|

  config.include ObjectCreationHelper
  config.include ObjectCreationMethods
  config.mock_with :rspec

  config.global_fixtures = :all

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  config.before(js: nil) do
    config.use_transactional_fixtures = true



Here headless (enables running selenium tests on a ci-server without a browser) and data_base cleaner are set up.
Database_cleaner will clean everything in the specified interval (in my case after each test) unless tables are specified in the “except” option for the database_cleaner strategy.
It is important to turn transactional fixtures off before running specs that require js and turn them back on after they have run
to ensure rspec spec still runs, assuming that there are spec files that have both test that require js and some that don’t require js.

require 'spec_helper'
require 'capybara/rspec'
require 'capybara/rails'
require 'database_cleaner'
require 'headless'

headless =

at_exit do
  unless ENV['RUNNING_CI']

def build_fixtures
  fixtures_folder = File.join(Rails.root.to_s, 'spec', 'fixtures')
  fixtures = Dir[File.join(fixtures_folder, '*.yml')].map { |f| File.basename(f, '.yml') }
  Fixtures.create_fixtures(fixtures_folder, fixtures)

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation, {:except => %w[ ]}

  # before each test that requires js, turn transactional fixtures off
  # build the fixtures and start the db cleaner
  config.before(js: true) do
    config.use_transactional_fixtures = false

  # after each spec with js, turn transactional fixtures back on
  # rebuild fixtures
  config.after(:each, js: true) do
    config.use_transactional_fixtures = true


Pretty straight forward, some clean up and checking if fixtures need rebuilding. Since database_cleaner will try to clean all exisiting tables
it is important to exclude database views specifically.

FixtureBuilder::Configuration.class_eval do

  def rebuild_fixtures?
    (@file_hashes != read_config) || Dir.glob('spec/fixtures/**/*.yml').empty?

  def files_to_check
    @files_to_check ||= []

  def delete_tables
    ActiveRecord::Base.connection.execute('SET FOREIGN_KEY_CHECKS=0')
    tables.each { |t| ActiveRecord::Base.connection.delete(delete_sql % ActiveRecord::Base.connection.quote_table_name(t)) }
    ActiveRecord::Base.connection.execute('SET FOREIGN_KEY_CHECKS=1')


FixtureBuilder.configure do |builder|
  builder.files_to_check = Dir["spec/support/fixture_builder.rb"]
  builder.skip_tables += ["current_post_stats_view"]
  builder.factory do

    united_states = Country.create! :name => "United States", :country_code => "US"
    Country.create! :name => "Canada", :country_code => "CA"

    admin_user = User.create! do |user|
      user.first_name = "Admin"
      user.last_name = "User" = ""
      user.password = "password"
      user.password_confirmation = "password"
      user.role = "admin"
    name("admin", admin_user)

  1. Marc Agas says:

    I was wondering if this approach is better than using FactoryGirl.

  2. Joseph Palermo says:

    I find FactoryGirl to be really great at first, but becomes really painful over time.

    Often your model graph gets pretty deep over time, on my current project, if I want a new object at the bottom of the graph, it has ~8 objects it depends on that also need to be created. This becomes incredibly expensive and I’ve found that it starts to have a large impact on test speed.

    The ability to use transactional fixtures means you can get all your fixtures back in a fresh state nearly instantly.

    For what it is worth, on my current project we use FactoryGirl inside of FixtureBuilder just to clean up the creation of objects, but still get the speed of transactional fixtures.

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *

Share This