I'm trying to test my rake task using rspec and it runs fine, but the problem is that the records aren't being deleted afterwards.
I've put config.use_transactional_fixtures = true in the config file to no affect. In other tests it's was working fine.
Here's my code:
require 'rspec'
require 'spec_helper'
require 'rake'
describe 'my_app rake tasks' do
describe 'rake_task_1' do
before { MyApp::Application.load_tasks }
it 'should test it!' do
10.times { create(:record) }
Rake::Task["rake_task_1"].invoke
Record.count.should == 10
end
end
end
In my rake task I'm executing a query using ActiveRecord::Base.connection.execute.
I'm sure it has something with SQL transitions in RSepc....
any ideas?
Have you tried using database_cleaner gem?
You can check the great article by Avdi Grimm about how to configure it.
config.use_transactional_fixtures = false
In file 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
Related
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
I have a simple scenario in my rspec feature:
require 'spec_helper'
feature 'CLIENT views results page' do
context 'from welcome/index form' do
let!(:location) { FactoryGirl.create :location, name: 'town' }
before :each do
visit '/'
end
scenario 'successfully', js: true do
expect(Location.count).to eq 1
fill_in 'from_address', with: 'Some address'
fill_in 'to_address', with: 'Another address'
click_button 'Search'
expect(page).to have_content 'Some address → Another address'
end
end
end
spec_helper:
require 'rubygems'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'factory_girl'
require 'database_cleaner'
require 'capybara/poltergeist'
FactoryGirl.reload
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.infer_base_class_for_anonymous_controllers = true
config.order = "random"
config.tty = true
config.mock_with :rspec
config.filter_run focus: true
config.run_all_when_everything_filtered = true
config.treat_symbols_as_metadata_keys_with_true_values = true
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
Capybara.javascript_driver = :poltergeist
Capybara.asset_host = "http://localhost:3000"
Capybara.server_port = 9887 + ENV['TEST_ENV_NUMBER'].to_i
And my scenario fails on some random step (after expect(Location.count).to eq 1) due to the fact, that there are no Location records:
(byebug) Location.all
[]
I think it might be one of two cases:
Either DatabaseCleaner cleans database before an example finishes
Or there are actually two threads with two databases, one of which (the one that is used by the app) is really empty
Gem versions:
rspec (2.14.1)
rspec-core (2.14.8)
rspec-rails (2.14.0)
phantomjs (1.9.7.1)
rails (3.2.21)
database_cleaner (0.9.1)
I remember having issues with this as well. My config for DB cleaning looks like this:
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
Maybe it has something to do with the order your before blocks are called. So if DatabaseCleaner.start is called before you wanted strategy is set, you might see such results.
Managed to solve this issue by migrating to
config.use_transactional_fixtures = true
instead of using DatabaseCleaner. Some workarounds are suggested to make transactional cleaning work with javascript tests. I chose this one:
(adding somewhere in the beginning of spec/spec_helper)
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || retrieve_connection
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
cause it seemed to work faster, still leaving some spontaneously failing tests (might not be the problem related to database).
When attempting to follow example on database_cleaner's GitHub page, I encountered the following error from RSpec:
ActiveRecord::StatementInvalid:
SQLite3::SQLException: cannot start a transaction within a transaction: begin transaction
The configuration used in spec_helper.rb is:
require 'spork'
require 'database_cleaner'
Spork.prefork do
# .. snip
RSpec.configure do |config|
# .. snip
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
end
end
Spork.each_run do
end
The accepted answer makes all tests slower (when it's not needed) by truncating after each one.
Just add
config.use_transactional_fixtures = false
when using database_cleaner.
If you have both config.use_transactional_fixtures = true and DatabaseCleaner.strategy = :transaction you're going to start a transaction inside another transaction and that's not allowed.
I found the solution to be changing the entire strategy to :truncation. Updated spec_helper:
require 'spork'
require 'database_cleaner'
Spork.prefork do
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
end
Spork.each_run do
end
I'm having an issue with JS request specs - basic visiting of a model edit page:
it "can edit a doc", :js => true do
doc = FactoryGirl.create(:doc) # tried with Doc.create as well
puts Doc.find(doc.id) # 1 <- so it's definitely in the DB!
visit edit_doc_path(doc)
end
Result: "ActiveRecord::RecordNotFound - Couldn't find doc with id=1"
The odd thing is it works with standard request spec. I tried both webkit and selenium drivers. My spec_helper looks like this (should be pretty standard):
RSpec.configure do |config|
config.use_transactional_fixtures = false
Capybara.javascript_driver = :webkit
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
config.before(:each, :type => :request) do
Capybara.reset_sessions!
end
end
Rails 3.1.4, no versioning for capybara, rspec, etc. test libraries.
Any input much appreciated! Thanks!
Seems like you have same problem as this:
Capybara with :js => true causes test to fail
Try setting DatabaseCleaner strategy to :truncation and see if it works
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
i really can't understand why DatabaseCleaner is not cleaning my test database. This is what i get prompting
1.9.2p290 :007 > DatabaseCleaner.clean
--
=> [#<DatabaseCleaner::Base:0x007fa7e4dd8b58 #autodetected=true, #orm=:active_record, #strategy=#<DatabaseCleaner::ActiveRecord::Transaction:0x007fa7e4dc14f8 #db=:default>>]
This seems not to set correctly the database (supposed to be :test), so i got a solution like
DatabaseCleaner[:active_record, :connection => :test].clean
# => nil
The gem seems to be set up correctly:
1.9.2p290 :007 > DatabaseCleaner[:active_record, :connection => :test]
#<DatabaseCleaner::Base:0x007fe8fcfd4868 #orm=:active_record, #strategy=#<DatabaseCleaner::ActiveRecord::Transaction:0x007fe8fcfd2748 #db=:test, #connection_hash={"adapter"=>"sqlite3", "database"=>"db/test.sqlite3", "pool"=>5, "timeout"=>5000}>, #db=:test>
This seems to setup correctly the test database, however it is still not going to clean properly the database. Any suggestions?
Thank you very much.
Even with database cleaner correctly configured it is easy to leave data lying around.
config.before(:suite) do
DatabaseCleaner.clean_with :truncation # clean DB of any leftover data
DatabaseCleaner.strategy = :transaction # rollback transactions between each test
Rails.application.load_seed # (optional) seed DB
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
The configuration above starts & runs the cleaner either side of each test.
If you then use before :all in your specs you can end up with data lying around:
describe User do
# Before all is outside the before :each
before :all do
#user = User.create(:email => 'hello#example.com')
end
...tests here
end
Here's my spec_helper.rb (slightly modified) - maybe that will help you?
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'database_cleaner'
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
Avdi Grimm's had a nice post recently on configuring database cleaner:
http://devblog.avdi.org/2012/08/31/configuring-database_cleaner-with-rails-rspec-capybara-and-selenium/
$ rails c test
> require 'database_cleaner'
> DatabaseCleaner.strategy = :truncation
> DatabaseCleaner.clean
https://github.com/DatabaseCleaner/database_cleaner