Closed conradwt closed 9 years ago
+1 to this. Almost exactly the same setup. No idea why it's not, can't track it down.
I'm having this same problem with the same setup (except with Postgres). One model in particular is not getting cleaned. I can tell because if I raise Subject.all.inspect
inside one of my rspec tests, it returns results when it shouldn't.
Very odd. My only guess is that the table doesn't exist when DatabaseCleaner queries for the existing tables. Could someone reproduce the bug in a sample rails app?
What are the names of the tables not being cleaned? Maybe that would provide a clue...
@bmabey In my case, the table name is jobs. Also, it doesn't effect the running specs but it's something that I noticed by looking at the contents of the database after they completed.
I was wrong. I've determined that it's actually not a particular table that isn't getting cleaned, but rather all tables after one particular model spec runs. If I ignore that spec from my suite, the problem doesn't occur.
Here is my spec_helper.rb: https://gist.github.com/3279090
I'm not using transactional_fixtures and I think I have everything set up properly, but for some reason after my suite runs, there's still a bunch of stuff left in my test database.
I even put this in the problem spec:
after(:all) do
puts Subject.all.count
DatabaseCleaner.clean
puts Subject.all.count
end
It outputs 7 both times.
If you tail the log for ActiveRecord or your DB do you see TRUNCATE commands being issued?
Add a puts DatabaseCleaner.connections.inspect
and paste what it outputs...
Hmm, I only see a truncate command in test.log before the suite runs: https://gist.github.com/3279394 (snipped at end)
I inspected the DC connections in my after(:all)
block and got [#<DatabaseCleaner::Base:0x000001038983d0 @autodetected=true, @orm=:active_record, @strategy=#<DatabaseCleaner::ActiveRecord::Transaction:0x00000103a607f8 @db=:default>>]
.
It's possible that DatabaseCleaner is never running after each test, even though I've specified it in my spec_helper.rb above. If I exclude what I thought was the problematic spec and run my suite, User.all
, for example, still returns entries in my Rails console's test environment.
If I destroy_all
on the Users, run the test suite again, they're back.
Theoretically, with DatabaseCleaner, this shouldn't be happening, right?
Oh right, you are using :transaction
so you shouldn't be seeing TRUNCATE
but seeing the transactions being rolled back. Try using the (slower) :deletion
strategy temporarily to see if that cleans it.
@bmabey I have removed all the data from table in question and ran the specs. Thus, the test database after running the specs should be empty if I'm using the transaction strategy. Is this correct in this scenario given the preconditions?
Yes, that is correct. Assuming that you aren't populating the table outside of a spec and your app isn't prematurely committing the transaction. That's why I suggested using another strategy like :deletion to help debug.
On Aug 6, 2012, at 5:57 PM, Conrad Taylor notifications@github.com wrote:
@bmabey I have removed all the data from table in question and ran the specs. Thus, the test database after running the specs should be empty if I'm using the transaction strategy. Is this correct in this scenario given the preconditions?
— Reply to this email directly or view it on GitHub.
Your latest comment just helped me figure it out. I remembered that I am, in fact, manually committing a transaction in a Class I am testing (e.g. MyModel.connection.commit_db_transaction
). I changed to the deletion strategy, which is a bit slower, while I investigate whether there's a way to avoid having to manually commit a transaction.
I would suggest sticking with :transaction
for the suite and then tagging certain specs that need to be cleaned via another strategy.
It seems that the MyISAM database engine doesn't support rollback. (http://lists.mysql.com/mysql/201528). So transaction strategy doesn't work in that case. When I created the db, my server was configured for MyISAM (for reasons I don't know), and this caused this fine and useful gem to fail. There is a mySQL warning available when rollback fails, and it would be a good idea to propagate this up into ruby-land somehow, as otherwise the failure is silent.
@lazylester I'll test things against PostgreSQL now that I'm doing mostly all client projects with this database engine.
I have the same problem when using Spork, RSpec (rails 2.12), mongoid, and Capybara (2.0.2).
It took a bit of googling and trying various solutions. Here is the one that worked for me in my spec_helper.rb
file.
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 'database_cleaner'
require 'capybara/rspec'
# 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
# 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
# Clean up the database
config.before(:suite) do
DatabaseCleaner.clean_with :truncation
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.orm = "mongoid"
end
config.before(:each) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean
end
config.after(:each) 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
Spork.each_run do
# This code will be run each time you run your specs.
ActiveSupport::Dependencies.clear
end
In summary I added the following in the before(:each)
block, as the commands from the before(:suite)
block seemed to be ignored
***DatabaseCleaner.strategy = :truncation***
Being newish to using this, not sure if its correct, but I've gained a lot of help from the community, so thought I would give back with what worked for me.
I'm having the same problem. My database is SQLite3 and my spec config is:
# spec/spec_helper.rb
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rspec'
require 'database_cleaner'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.fixture_path = "#{::Rails.root}/spec/fixtures"
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
config.order = "random"
end
And in my models spec:
# spec/models/task_spec.rb
require 'spec_helper'
describe Task do
subject(:task) { FactoryGirl.build(:task) }
# ...
it "should not update if #active field is false" do
updated_at = task.updated_at
task.active= false
task.destroy
expect(task.updated_at).to eq updated_at
expect(task.active).to be_false
expect(Task.actives.count).to have(:no).items
end
end
When I'm testing how many registers exist in my database expect(Task.actives.count).to have(:no).items
, it's returning to me the number of test in my file. I have eight tests, so .count
is returning this value.
Thoughts? :confused:
This seems to be affecting me, too. Transactional Fixtures had been enabled... But I disabled it for some Capybara tests. In the specs where DatabaseCleaner should be setting up transactions, the Rails log instead looks like:
(0.4ms) SAVEPOINT active_record_1
SQL (0.5ms) INSERT INTO `settings` (<SNIP>) VALUES (<SNIP>)
(0.3ms) RELEASE SAVEPOINT active_record_1
(0.3ms) SAVEPOINT active_record_1
SQL (0.5ms) INSERT INTO `settings` (<SNIP>) VALUES (<SNIP>)
(0.2ms) RELEASE SAVEPOINT active_record_1
(0.2ms) SAVEPOINT active_record_1
SQL (0.5ms) INSERT INTO `settings` (<SNIP>) VALUES (<SNIP>)
(0.3ms) RELEASE SAVEPOINT active_record_1
The fixtures are created using FactoryGirl. I'm not sure what I should be seeing, but when I'm in a Pry session in the middle of my spec and I create a record -- it continues to exist after the spec has completed. I don't see any SAVEPOINT information being inserted, etc. Something is definitely borked.
Ruby 2.0.0p451
Rails 4.0.4
database_cleaner 1.2.0
PostgreSQL 9.3.4
I believe I am experiencing this as well. In my case it seems that in a feature test (integration test) all but one table have been cleaned (emptied).
Here is what I have in test/test_helper.rb:
require 'database_cleaner'
DatabaseCleaner.strategy = :transaction
class MiniTest::Unit::TestCase
def setup
DatabaseCleaner.start
end
def teardown
DatabaseCleaner.clean
end
end
For the time being I added the following to the integration test to clean the affected table:
def setup
Event.delete_all
end
Note: The fixtures are created using FactoryGirl.
@abatko I tend to do all cleanup within the teardown method. However, the setup works as well but it will leave records in the database after the last test. These days I tend to move away from the setup and teardown methods because I really like having self contained integration and unit tests. You're doing the right thing because it allows you to move forward within your development.
I am going out on a limb to say that after some painstaking debugging I seem to have resolved this issue for myself. As I mentioned earlier, I am using FactoryGirl, and it turns out that I was incorrectly creating/assigning attributes dynamically (aka lazy attributes).
Wrong:
event_id FactoryGirl.create(:event).id
Correct:
event_id { FactoryGirl.create(:event).id }
After making this change I have not been able to reproduce the error, and this also means that I removed setup
/ delete_all
.
@abatko Is this code within your factory file? If this is the case, then you should be able to simply do the following:
FactoryGirl.define do
factory :some_object do
attribute1 "attribute1"
attribute2 "attribute2"
event
end
factory :event do
attribute3 "attribute3"
attribute4 "attribute4"
end
end
Now, you can do the following within your test code:
object = FactoryGirl.create(:some_object)
event_id = object.event.id
§
Is anyone still experiencing this problem? I'd like to close it, because it's too broad and I'd prefer it if you opened new issues that are more specific (ie. ORM + DBMS + strategy)
If you're still having a similar problem, please open a new issue specifying ORM + DBMS + strategy (optional)
Thanks!
I have encountered the problem myself in a Rails 3.2 + Rspec 3 environment. Changing my rails_helper.rb to :
config.use_transactional_fixtures = false
solved my problems. A
I was running into a similar issue, but eventually got it to work with the truncation
strategy. My issue ended up being that I was using ActiveRecord to create some of the objects I was working with in my tests when I should have been using factories I had setup with FactoryGirl. Hope that helps someone.
I had a similar case: some user records were not cleaned from DB. My analysis showed that those records that assigned to Thread.current
are not cleaned automatically by DatabaseCleaner
.
In the end, I come up with the following fix:
config.after(:each) do
# Thread.current[:current_user] is set in some tests
# it should be cleaned before database cleaner runs, otherwise it won't be dropped from DB.
Thread.current[:current_user] = nil
DatabaseCleaner.clean
puts User.count # this output along with running "rspec --format d" can show the places causing issues in the app
end
The database, MySQL, isn't being properly cleaned using the RSpec recipe below:
Setup:
Lastly, this isn't so much of an issue with the unit tests but causes issues with the controller and acceptance tests.