Cannot use with database_cleaner gem
leebrooks0 opened this issue · comments
I am trying to use your gem with database_cleaner
. In my testhelper.rb
I have the following:
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
MiniTest::TestCase.add_setup_hook { DatabaseCleaner.start }
MiniTest::TestCase.add_teardown_hook { DatabaseCleaner.clean }
The hooks are necessary as if you use before and after like they do here:
https://github.com/bmabey/database_cleaner
you will override them when you use before
and after
blocks in your test.
I keep getting this message though:
rake aborted!
NameError: uninitialized constant Minitest::TestCase
/home/lee/Code/mobifit/test/test_helper.rb:47:in `<top (required)>'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/sub_test_task.rb:114:in `block (3 levels) in define'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/sub_test_task.rb:114:in `each'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/sub_test_task.rb:114:in `block (2 levels) in define'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/sub_test_task.rb:113:in `each'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/sub_test_task.rb:113:in `block in define'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/sub_test_task.rb:31:in `create_and_run_single_test'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/sub_test_task.rb:17:in `invoke_rake_task'
/home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.0.rc2/lib/rails/test_unit/testing.rake:8:in `block in <top (required)>'
-e:1:in `<main>'
Tasks: TOP => test:single
(See full trace by running task with --trace)
Googling yields nothing, so I don't know where the problem lies.
The examples on the database cleaner repo look outdated and/or just wrong. There is no such things as :each
in MiniTest. https://github.com/bmabey/database_cleaner#minitest-example
I think you are adding too much technical details here. May I suggest the following in your test_helper.rb file.
ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
DatabaseCleaner.strategy = :truncation
before { DatabaseCleaner.start }
after { DatabaseCleaner.clean }
end
First, if DB cleaner is in your test group, it is required for you. No need to do it again. Second, you are trying to hook into MiniTest, that is too low level, you want to hook into ActiveSupport::Test case and that is why I have these examples shown this way. MiniTest does not have a notion of before/after stacks. This gem extends MiniTest (for AS::TC) to maintain the Rails setup/teardown callback style that allows you to push multiple before/after blocks.
Also, for the record, I high recommend using a clean DB in Rails. Using factories is awesome. But so are DB transactions with fixtures. May I suggest the following reading/tools on the topic.
- https://github.com/metaskills/named_seeds
- https://github.com/metaskills/holy_grail_harness#factories-and-fixtures
FYI, I will have some patches in the named_seeds gem today for Rails 4.1 compatibility. Also, 4.1.0 is out as of yesterday too.
Thanks for the advice, I removed require 'database_cleaner
, and used the snippet you suggested (except in Rails 4.1 the test db is automatically maintained, http://edgeguides.rubyonrails.org/4_1_release_notes.html#railties-notable-changes), and it works correctly.
I read through the links you gave, and they were very interesting, thank you, I am now using minitest-focus (from holy_grail_harness - have been needing something just like that...), named seeds is also looking very useful, my app has users with certain roles etc that are constantly inserted into the database for a large amount of tests.
Truncation as your second link pointed out is very, very slow, my test suite just slowed down about 10 fold, purely due to truncating after each test. However, I am using Devise, and DeviseAsync to send the emails with DelayedJob, but DeviseAync does not send the emails until after commit, and that can cause problems in your integration tests (as in full stack, not what rails calls an integration tests), see https://github.com/mhfs/devise-async#testing.
I think the best idea is to scrap DeviseAsync, and just override the relevant Devise methods to send, the mails with DelayedJob as suggested here: http://stackoverflow.com/questions/13531515/disable-devise-confirmable-mails
Turns out, my test.rb file was missing this:
# You need to set up the default url options for the Devise mailer in each environment
config.action_mailer.default_url_options = { host: 'localhost:3000' }
that was why it wasn't sending, DeviseAsync then works correctly with transactional tests, never mind what the readme says.
Awesome and congrats. Thanks for checking out my other info and sharing your details too.
Trying to follow your example, I get thrown NoMethodError: undefined method
before' for ActiveSupport::TestCase:Class`
My test_helper.rb
:
ENV['RAILS_ENV'] = 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/pride' # awesome colorful output
require 'minitest/reporters' # fancier output format
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
# Requires supporting ruby files with custom matchers and macros, etc,
# in test/support/ and its subdirectories.
Dir[Rails.root.join('test/support/**/*.rb')].each{ |f| require f }
RedSteel::Application.reload_routes!
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
DatabaseCleaner.strategy = :transaction
before :each do
DatabaseCleaner.start
DeferredGarbageCollection.start
end
after :each do
DatabaseCleaner.clean
DeferredGarbageCollection.reconsider
end
end
class ActionController::TestCase
include Devise::TestHelpers
end
I should add as well that I have some custom rake tasks setup for *_spec
files:
namespace :spec do
Rails::TestTask.new(:all) do |t|
t.libs << 'test'
t.pattern = 'test/**/*_spec.rb'
end
namespace :all do
desc 'Run tests quickly, but also reset db'
task :db => %w[db:test:prepare spec:all]
end
end
Rake::Task[:test].enhance{ Rake::Task['spec:all'].invoke }
rake test
works as expect, but rake spec:all
provides the error above.
@elsom25 :each is ignored http://bfts.rubyforge.org/minitest/MiniTest/Spec.html#method-c-before, although that is not the answer to your question. Also, why are you using DatabaseCleaner if you need transactional tests, as Rails already gives you transactional tests?
oh sorry, that was a mistype, though changing that naturally doesn't remove the error.
before
and after
have been replaced with setup
and teardown
for anyone who is experiencing the NoMethodError: undefined method 'before' for ActiveSupport::TestCase:Class
error.
The following works in Rails 5:
class ActiveSupport::TestCase
include FactoryGirl::Syntax::Methods
ActiveRecord::Migration.check_pending!
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.logger = Rails.logger
setup { DatabaseCleaner.start }
teardown { DatabaseCleaner.clean }
end
@dmvt The setup
and teardown
blocks have been in Rails for as long as I can remember. Rails has always made those methods use the callback chain so you can stack them up. This gem has always delegated to those methods so MiniTest's before/after syntax follows that practice. More details here:
- https://github.com/metaskills/minitest-spec-rails#setup--teardown-compatability
- https://github.com/metaskills/minitest-spec-rails/blob/master/lib/minitest-spec-rails/dsl.rb#L16-L22
Lastly, I have never had an issue using this gem with DatabaseCleaner. Hope that info is helpful if anyone is having issues. Please share details if you are.