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.
spec_helper.rb
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 end end
accptance_helper.rb
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 = Headless.new headless.start at_exit do unless ENV['RUNNING_CI'] headless.destroy end end def build_fixtures Fixtures.reset_cache fixtures_folder = File.join(Rails.root.to_s, 'spec', 'fixtures') fixtures = Dir[File.join(fixtures_folder, '*.yml')].map { |f| File.basename(f, '.yml') } DatabaseCleaner.clean Fixtures.create_fixtures(fixtures_folder, fixtures) end RSpec.configure do |config| config.before(:suite) do DatabaseCleaner.strategy = :truncation, {:except => %w[ ]} DatabaseCleaner.clean_with(:truncation) end # 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 build_fixtures() DatabaseCleaner.start end # after each spec with js, turn transactional fixtures back on # rebuild fixtures config.after(:each, js: true) do config.use_transactional_fixtures = true build_fixtures() end end
fixture_builder.rb
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? end def files_to_check @files_to_check ||= [] end 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)) } ensure ActiveRecord::Base.connection.execute('SET FOREIGN_KEY_CHECKS=1') end end 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.email = "admin@super_site_.com" user.password = "password" user.password_confirmation = "password" user.role = "admin" end name("admin", admin_user) end end
About the Author