database_cleaner
Strategies for cleaning databases in Ruby. Can be used to ensure a clean state for testing.
database_cleaner | RubyGems.org | your community gem host
I have an old Rails application upgraded to version 3.2.11 that has a lot of request specifications written using capybara version 1.0.1 and running using the selenium driver. The database are cleaned after each test using database_cleaner using the truncation strategy.
I want to use poltergeist instead of selenium and upgraded capybara from 1.0.1 to 1.1.4 to be able to use the latest version of poltergeist. Only changing the capybara gem (and its dependencies) introduced problems running my specs.
I consistently get deadlock errors from my Postgresql database in the cleanup handler after each spec. My spec_helper is pretty basic and looks like this:
RSpec.configure do |config|
config.mock_with :rspec
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
The error I get is like this:
An error occurred in an after hook
ActiveRecord::StatementInvalid: PG::Error: ERROR: deadlock detected
DETAIL: Process 41747 waits for AccessExclusiveLock on relation 17612 of database 16396; blocked by process 41752.
Process 41752 waits for RowExclusiveLock on relation 17529 of database 16396; blocked by process 41747.
HINT: See server log for query details.
: ALTER TABLE "aaa" ENABLE TRIGGER ALL;ALTER TABLE "bbbb" ENABLE TRIGGER ALL;ALTER TABLE "ccc" ENABLE TRIGGER ALL;
occurred at /xxx/.bundle/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:652:in `async_exec'
I use FactoryGirl to create test data but otherwise nothing special IMO.
I haven't been able to figure out what holds the other end of deadlock that is created by database_cleaner. Any ideas to figure that out are most welcome.
Anybody know of any changes between capybara 1.0.1 and 1.1.4 that has changed and may have started to cause these issues?
Source: (StackOverflow)
i would like to disable use_transactional_fixtures = false in ministest to catch after_commit callback. What and where should i set-up?
Source: (StackOverflow)
I saw this cool method for only using Database cleaners :truncation for capybara test using :js => true
In spec_helper.rb:
config.before(:each) do
DatabaseCleaner.strategy = if example.metadata[:js]
:truncation
else
:transaction
end
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
The problem is that any feature test done with capybara seems to need the cleaning strategy to be :truncation.
All the other specs, however, are fine with :transaction, which is significantly faster.
Is there a way of specifying strategy for only capybara feature tests? SOmething like:
DataCleaner.strategy( :truncation ) if :type => :feature
Source: (StackOverflow)
I'm using Turnip and Ruby on Rails. I have scenarios with and without using javascript. I want to use the transaction
DatabaseCleaner strategy for the non-javascript scenarios and the truncation
strategy for scenarios marked by @javascript
, @selenium
and etc.
I'm using following solution for Rspec Features
config.around(:each, :js => true) do |ex|
DatabaseCleaner.strategy = :truncation
ex.run
DatabaseCleaner.strategy = :transaction
end
But it doesn't work in Turnip case. What is the best way to make it works as I expected? Or in other words how to specify turnip scenario marked by @javascript
(or @selenium
and etc) tag in config.before
?
Source: (StackOverflow)
I'd like to use zeus (0.13.3) to preload my rails environment for an rails (3.2.11) app on ruby 2.0.0 and use database_cleaner (0.9.1) to clean the databases.
This is working fine if as long as I use only one mysql database.
In the app we have to use two different mysql databases.
Edit: What needs to be mentioned is, that I use the shared connection hack, which is described here.
Running my specs without using zeus is working like expected. But if I use it, every test is failing in the moment when a record is created with the error:
undefined method `query_options' for nil:NilClass
How can this be solved?
The setup is like that:
config/database.yml
test:
database: app_test
...
test_second_db:
database: other_test
...
In an abstract base class for all the models using the second connection we do
models/second_db/base.rb
module SecondDB
class Base < ActiveRecord::Base
establish_connection "#{Rails.env}_second_db"
self.abstract_class = true
end
end
In my spec_helper.rb file I setup the database_cleaner:
spec/spec_helper.rb
require 'database_cleaner'
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner[:active_record,{:connection => :test_second_db}].strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
DatabaseCleaner[:active_record,{:connection => :test_second_db}].start
end
config.after(:each) do
DatabaseCleaner.clean
DatabaseCleaner[:active_record,{:connection => :test_second_db}].clean
end
end
edit:
spec/support/shared_connection.rb
class ActiveRecord::Base
mattr_accessor :shared_connection
@@shared_connection = nil
def self.connection
@@shared_connection || retrieve_connection
end
end
spec/support/shared_connection.rb
Source: (StackOverflow)
I'm trying to complete some tests for a rails 4 app and I keep encountering an issue with database_cleaner.
The issue is the database is not being cleaned and warnings keep raising:
DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
.DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
WARNING: there is already a transaction in progress
WARNING: there is already a transaction in progress
.FFFFDEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
.DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
WARNING: there is already a transaction in progress
.DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
WARNING: there is already a transaction in progress
.WARNING: there is already a transaction in progress
DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
.DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
WARNING: there is already a transaction in progress
.DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
WARNING: there is already a transaction in progress
.DEPRECATION WARNING: #increment_open_transactions is deprecated and has no effect. (called from block (3 levels) in <top (required)> at /Users/davidhahn/Dev/cta-projects/user-management2/spec/spec_helper.rb:49)
WARNING: there is already a transaction in progress
WARNING: there is already a transaction in progress
The configuration I have setup in the spec helper is:
require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'
Spork.prefork do
# Loading more in this block will cause your tests to run faster. However,
# if you change any configuration or code from libraries loaded here, you'll
# need to restart spork for it take effect.
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
# require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rspec'
require 'database_cleaner'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
config.mock_with :rspec
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.filter_run focus: true
config.run_all_when_everything_filtered = true
# 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 = false
config.before :each do
if Capybara.current_driver == :rack_test
DatabaseCleaner.strategy = :transaction
else
DatabaseCleaner.strategy = :truncation
end
DatabaseCleaner.start
end
config.after do
DatabaseCleaner.clean
end
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
# config.infer_base_class_for_anonymous_controllers = false
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
end
end
And finally here is my gemfile
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.0.0.beta1'
gem 'pg'
gem 'haml-rails', '~> 0.4'
gem 'twitter-bootstrap-rails', '~> 2.2.0'
gem 'annotate', '~> 2.5.0'
group :test do
gem 'rspec', '~> 2.13.0'
gem 'rspec-rails', '~> 2.13.0'
gem 'guard-rspec', '~> 1.2.1'
gem 'guard-spork', '~> 1.4.2'
gem 'capybara', '~> 2.0.2'
gem 'spork', '~> 0.9.2'
gem 'factory_girl_rails', '~> 4.1.0'
gem 'shoulda-matchers', '~> 1.4.2'
gem 'database_cleaner', '~> 0.9.1'
gem 'launchy', '~> 2.2.0'
gem 'rb-fsevent', '~> 0.9.2'
gem 'growl', '~> 1.0.3'
end
group :development do
gem 'better_errors' ,'~> 0.6.0'
gem 'binding_of_caller', '~> 0.7.1'
end
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 4.0.0.beta1'
gem 'coffee-rails', '~> 4.0.0.beta1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 1.0.1'
Any help on this issue would be really helpful. Thank you!
Source: (StackOverflow)
I am currently using cucumber and databasecleaner to test my application.
And currently in my env.rb
i have the setup of the cleaner as:
DatabaseCleaner.strategy = :truncation, {:except => %w[TABLE]}
After do
DatabaseCleaner.clean
end
This way I can keep the data in TABLE
.
But I would also like to keep a single entry in a different table between tests. Is there any way I can achieve that or do I have to recreate it all the time with a Before
hook?
Source: (StackOverflow)
I am asking this because in the articles I have read so far, concerning rspec and the database_cleaner gem I see the line config.use_transactional_fixtures = false
. If I use the database_cleaner gem couldn't I just delete this line?
Source: (StackOverflow)
I use ActiveRecord Fixtures to define preset data for tests.
I use the database_cleaner gem to reset the database between tests. I follow the approach described by Avdi Grimm to use truncation for javascript tests, but transactions for non-javascript tests.
Most advice regarding database_cleaner tells you to set config.use_transactional_fixtures = false
, without discussing the implications. The implication is that when AR creates the Fixture data, it does not start a transaction. The idea is that database_cleaner will handle starting the transaction, if you use the :transaction
strategy.
The problem is that ActiveRecord creates the Fixture data before you get a chance to call DatabaseCleaner.start
. That means the fixture data is not part of the transaction, so when database_cleaner rolls back the transaction, the fixture data remains, polluting follow up tests that may not expect that fixture data.
How do I get ActiveRecord to create the Fixture data within the context of the database_cleaner transaction?
I'm using Rails 4.1.0rc1, rspec-rails 2.14.2, rspec 2.14.1, database_cleaner 1.2.0.
Source: (StackOverflow)
This config worked fine when I was using sqlite:
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
controller.stub(:should_navigate_user?).and_return(false) rescue ""
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
When I switched to PostgreSQL I began getting errors when tests depended on the id number of entries in the database. I looked at the database during the tests and it was never cleaning the database.
If I switch to the following config:
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.clean
controller.stub(:should_navigate_user?).and_return(false) rescue ""
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
All of my tests pass, but I'm having to call clean before and after my methods tests?
I shouldn't have to clean the database before and after each test - right? I feel like I'm misunderstanding something somewhere. What am I failing to understand.
Source: (StackOverflow)
In my project I use database multi-tenancy 'apartment' gem.
config/initializers/apartment.rb
Apartment.configure do |config|
config.excluded_models = %w{ User Company }
end
To clean up the database it tests I use 'database_cleaner' gem
spec/rails_helper.rb
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do |example|
DatabaseCleaner.strategy= example.metadata[:js] ? :truncation : :transaction
DatabaseCleaner.start
Apartment::Tenant.switch!('app')
end
config.after(:each) do
Apartment::Tenant.switch!
DatabaseCleaner.clean
end
end
In RSpec tests with Capybara truncation strategy clean after each test only public schema where only the user and company.
Before test start
Company.count#=> 0
Other schemes are not cleared.
Before test start
SomeModelInCompanySchema.count#=> 240
How to clear data in another scheme
Source: (StackOverflow)
My rspec tests seem to run extremely slow even with guard & spork.
Finished in 5.36 seconds
13 examples, 2 failures
I understand that there are several things I can do to optimize my tests & reduce interaction with the database, but I strongly suspect that the spec_helper has been improperly setup. I'm on rails 3.2.11 with mongoid. Database cleaner cleans up after every run.
spec_helper.rb
require 'rubygems'
require 'spork'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rspec'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
DatabaseCleaner[:mongoid].strategy = :truncation
RSpec.configure do |config|
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
config.filter_run focus: true
config.filter_run_excluding :remove => true
config.run_all_when_everything_filtered = true
config.include Mongoid::Matchers
config.include Capybara::DSL
ActiveSupport::Dependencies.clear
end
end
Spork.each_run do
Fabrication.clear_definitions
RSpec.configure do |config|
config.before(:each) do
DatabaseCleaner.clean
end
end
end
UPDATE: The problem was with one of my tests. It was taking 3 seconds. Please check @Sam Peacey's answer for the command I used to get the below result
Dynamic Model should destroy collection when related source is destroyed
2.46 seconds ./spec/models/dynamic_model_spec.rb:10
Dynamic Model Validations should validate uniqueness
0.66357 seconds ./spec/models/dynamic_model_spec.rb:69
Source: (StackOverflow)
I have the following Cucumber feature testing an input form using typeahead.js:
@javascript
Scenario: Creating a battery using typeahead
When I create a new battery using typeahead
Then I should be on the show battery page
And I should see the battery created message
The test fails on the second step with the following error message:
ActiveRecord::RecordNotFound (ActiveRecord::RecordNotFound)
./features/step_definitions/admin/car_part_steps/battery_steps.rb:37:in `/^I should be on the show battery page$/'
features/admin/creating_car_parts/creating_batteries.feature:20:in `Then I should be on the show battery page'
The relevant step definitions are as follows:
When /^I create a new battery using typeahead$/ do
select_from_typeahead :field => 'battery_manufacturer_typeahead',
:select => @manufacturer.name
fill_in 'Type', :with => '700W'
click_button 'Create Battery'
end
Then /^I should be on the show battery page$/ do
battery = Battery.find_by_type_and_manufacturer_id!('700W', @manufacturer.id)
current_path.should == admin_battery_path(battery)
page.should have_content(battery.type)
end
The select_from_typeahead function is as follows:
def select_from_typeahead(params)
params[:js_field] ||= params[:field]
params[:select_typeahead] ||= params[:select]
fill_in params[:field], :with => params[:select][0, 2]
page.execute_script "$('##{params[:js_field]}').trigger('focus')"
page.execute_script "$('##{params[:js_field]}').trigger('keydown')"
sleep 0.5
page.execute_script "$('.tt-suggestion:contains(\"#{params[:select_typeahead]}\")').trigger('mouseenter').trigger('click')"
end
The problem appears not to have anything to do with the typeahead itself however, as the code works in the browser, and if I add some debug output, I notice that the battery gets saved to the database in the first step when running the test as well, it just mysteriously disappears before the second step runs.
I think it's an issue with database_cleaner, as I know that doesn't play nice with Javascript when set to use transactions, but I've already tried setting it to use truncation instead and disabled transactional fixtures and it still doesn't work.
My features/support/env.rb currently looks like this:
require 'simplecov'
SimpleCov.start 'rails'
require 'cucumber/rails'
Capybara.default_selector = :css
Capybara.javascript_driver = :webkit
ActionController::Base.allow_rescue = false
Cucumber::Rails::World.use_transactional_fixtures = false
DatabaseCleaner.strategy = :truncation
Cucumber::Rails::Database.javascript_strategy = :truncation
My environment is as follows:
rails 4.0.2
cucumber 1.3.10
cucumber-rails 1.4.0
capybara 2.2.0
capybara-webkit 1.1.0
database_cleaner 1.2.0
Am I missing something, is there some other way database_cleaner might still interfere with my test, or is it something else entirely that I haven't thought of?
Any ideas would be very welcome!
Source: (StackOverflow)
I have gem devise
and gem apartment
which I'm using to create separate schemas for each devise's user account.
Apartment's doc and advice in that issue suggest to use Rack middleware to switch between tenants. In that case it's not possible (as far as I know) as I have it user depended rather than request depended.
All works just great except my RSpec tests. The problem is that after every test database is not clean properly (it doesn't remove schema for new created user). All tests pass if I run a small set of them but if I run to many than Faker::Internet.first_name
generates usernames that already was taken (which is not valid).
So this is how I did it:
app/controllers/application_controller.rb
def scope_tenant
Apartment::Database.switch(current_user.username)
end
app/controllers/albums_controller.rb (album model belong_to :user
)
class AlbumsController < ApplicationController
before_action :authenticate_user! # devise magic
before_action :scope_tenant
app/model/user.rb
after_create :create_schema
private
def create_schema
Apartment::Database.create(self.username)
end
This is what I've added to my specs:
spec/factories/user.rb
FactoryGirl.define do
factory :user do
username { Faker::Name.first_name }
email { Faker::Internet.email("#{username}") }
password "login_as will not use it anyway"
end
end
spec/support/auth_helpers.rb
Warden.test_mode!
def login_and_switch_schema(user)
login_as(user)
Apartment::Database.switch(user.username) # for some reason `login_as()` didn't do that by itself
end
spec/features/albums_spec.rb
feature "Album Pages" do
given(:user) { create(:user) }
given(:album) { create(:album) }
around :each do
login_and_switch_schema user
end
scenario...
As I have some tests with js: true
than I have that:
spec/support/database_cleaner.rb
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
Current commit for all sources are available at my github here.
So.. the main question is: how to clean database created schemas for each user after test ? I'll appreciate any other comment as well. Thank you in advance for help.
Source: (StackOverflow)
I am writing a test using RSpec and FactoryGirl. In my models DataMappers have been used. Here in RSpec I am testing two methods update and index function of my controller where I am using two objects A, B and C. I have created them by using FactoryGirl as follows:
before(:each) do
@A = FactoryGirl.create(:A)
@B = FactoryGirl.create(:B)
@C = FactoryGirl.create(:C)
end
Now I want to clean them after each test with DataBase Cleaner Gem. I have searched it in Google but most of the articles talk about how to use DataBase cleaner Gem with ActiveRecord but none of them clearly specify how to use DataBaseCleaner gem with DataMapper. So if anyone gives me small example of RSpec file with DataBase cleaner where DataMapper have been used, I will be really grateful. Thanks in advance.
Source: (StackOverflow)