Speed Up tests without database interaction - ruby-on-rails

I've added some :js => true tests to my project and had to integrate the database_cleaner gem to make it work. Now my tests, even the one's that don't use a database are slowed down considerably. Is there a way to skip database access for mocked/non-db-based tests?
Relevant part of the spec_helper.rb
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end

You can use DatabaseCleaner only if it need
spec_helper.rb
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
if :without_db != example.metadata[:type]
DatabaseCleaner.start
end
end
config.after(:each) do
if :without_db != example.metadata[:type]
DatabaseCleaner.clean
end
end
user_spec.rb
describe User, :type => :without_db do
it 'should be valid' do
should be_valid
end
end

Related

how to clean database before running the each spec file?

I want to clear my test database before running the each spec files.
I am already using rspec with factory girl.
Thanks,
Hare
Add to RSpec.configure block in your spec_helper.rb
config.before(:suite) do
DatabaseCleaner.clean_with :truncation
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
Must work
In your spec_helper.rb,
inside the RSpec.configure block
RSpec.configure do |config|
# ...
config.before(:suite) do
DatabaseCleaner.clean_with :transaction
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:all) do
DatabaseCleaner.start
end
config.after(:all) do
DatabaseCleaner.clean
end
# ...
end
before(:all) and after(:all) runs for every spec file and not before and after the whole suite. So, for every spec file you will be able to clear database using any of the three strategies :transaction, :truncation, :deletion
This is what I typically do for DatabaseCleaner
# Database Cleaner
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
That will make sure you have a clean database for each test.
Checkout a related, albeit old, article by Avdi for more info.

Resetting table IDs and re-creating the test DB with Rspec on Rails

I have various tests that create models using FactoryGirl in Rails
it "does something" do
user = create(:user)
...
expect(user.name).to eq("foo")
end
I noticed that each time I run the spec suite, it does not reset the table id's on the test schema (using Postgres). So after several executions the user might have an id of something like 2894.
I use Database Cleaner to clean my DB between subsequent runs - see below.
Is there a way to reset table ID's directly between rspec runs? A company I previously worked at did it with their app, but I'm not aware how.
If #1 is not an option, is it possible to drop and recreate the test DB between runs?
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:deletion)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :deletion
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
I am also using DatabaseCleaner gem and don't experience the same issue you do (though I'm using mysql instead).
Not sure if this helps in your case but would be worth trying my configuration:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
Rails.application.load_seed
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
My rails_helper.rb
require 'support/database_cleaner'
RSpec.configure do |config|
config.use_transactional_fixtures = false

DB Cleaner not cleaning database after each test after switching from sqlite to PostgreSQL

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.
I'm using postgres with the database cleaner. Its working well now, but I remember having trouble at first. I pasted my config below. You can stick this in your spec_helper.rb, or in another file such as /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
Also make sure you turn the transactional fixtures off in the spec_helper:
config.use_transactional_fixtures = false
You used sqlite in non-persistent mode. PostgreSQL doesn't have such options, always persistent. Use drop database/create database to clean it complettely.

Rails Rspec Capybara and DatabaseCleaner - using truncation only on feature tests

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
this should do it, let me know
config.after(:all, :type => :feature) do
DatabaseCleaner.clean_with :truncation
end

tests and database_cleaner for multiple databases

We have a Mailbox model which uses a secondary DB to which another mail app also connects. This is called using
establish_connection :mail_database
Now, I suppose I could attempt to wrap that in an if statement so it uses a different connection for the test environment, but I'm wondering how I could keep this database clean, preferably using database_cleaner which we already use for the 'regular' database.
I hope someone can nudge me in the right direction.
I have a rails3.2.10 application tested with rspec (2.12.0) and using database_cleaner (0.9.1 f4b44bb) having two database connections for mysql.
These are set in the database.yml something like:
test:
...
database: my_app_test
test_my_second_connection:
...
database: my_second_connection_test
The second database is connected in the model class with establish connection.
I was able to use the following settings in my spec/spec_helper.rb file according to the manual of database_cleaner :
require 'database_cleaner'
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].start
end
config.after(:each) do
DatabaseCleaner.clean
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].clean
end
end
Additionally I have to use for some parts of the test suite non-transactional fixtures. So I had to add the meta information :db_truncate => true in my specs and the settings like this in order to change the strategy in test run:
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].strategy = :transaction
end
config.before(:each) do
if example.metadata[:db_truncation]
DatabaseCleaner.strategy = :truncation
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].strategy = :truncation
else
DatabaseCleaner.start
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].start
end
end
config.after(:each) do
DatabaseCleaner.clean
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].clean
if example.metadata[:db_truncation]
DatabaseCleaner.strategy = :transaction
DatabaseCleaner[:active_record,{:connection => :test_my_second_connection}].strategy = :transaction
end
end
****set database to clean by database cleaner in rails:-****
config.before(:suite) do
DatabaseCleaner[:active_record, :connection => :test].clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner[:active_record, :connection => :test].strategy = :transaction
end
config.before(:each) do
DatabaseCleaner[:active_record, :connection => :test].start
end
config.after(:each) do
DatabaseCleaner[:active_record, :connection => :test].clean
end

Resources