Rake doesn't create Mailer Templates when running RSpec - ruby-on-rails

In our project we have rake task, that creates mailer templates in database.
While running all specs, some of them are failing saying that the db record for some mailers don't exist.
Any ideas on what could be the reason for this and how to fix it?
Here the example of the task to create Mailer template.
desc "Creates mailer templates"
task create_mailers: :environment do
MailerTemplate.delete_all
I18n.available_locales.each do |locale|
MailerTemplate.create(locale: locale, mailer: "info#action", content: %{<p>Content</p>})
end
end
This is my database_cleaner.rb file
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:deletion)
Rake::Task["create_mailers"].invoke
end
config.around(:each) do |example|
DatabaseCleaner.strategy = example.metadata[:js] ? :deletion: :transaction
DatabaseCleaner.cleaning do
example.run
end
end
config.after(:each) do
Capybara.reset_sessions!
DatabaseCleaner.clean
end
end

Related

Rails: How do I ensure that the db reverts to its original state after tests?

I'm trying to write a test that involves creating a new user. However, the test fails all but the first time because the user remains permanently in the db after the initial run.
require 'test_helper'
require 'minitest/autorun'
describe UserMailer < ActionMailer::TestCase do
it 'will send an email when a new user is created' do
original_mail_count = ActionMailer::Base.deliveries.count
User.create(email: "new_user#test.com", password: "password").save
ActionMailer::Base.deliveries.count.must_equal original_mail_count + 1
end
end
How do I ensure that the db returns to its pre-test state after the test is run?
Use database_cleaner gem
Example usage:
# spec_helper.rb
RSpec.configure do |config|
config.before(:each) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end

Rspec and database_cleaner only remove the data added by the tests

I want to be able to always have access to my seed data on my test database.
I understand database_cleaner will remove everything if it's set up that way.
I try to remove everything and then reloading the seed, but when I try to use js: true on a test, the seed never gets loaded so i get errors saying data does not exist.
My spec_helper.rb
RSpec.configure do |config|
# before the entire test suite runs, clear the test database out completely
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
# sets the default database cleaning strategy to be transactions (very fast)
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
# For these types of tests, transactions won’t work. We must use truncation
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
# hook up database_cleaner around the beginning and end of each test, telling it to execute whatever cleanup strategy we selected beforehand.
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
# reload the seed so we have data to play with
end
config.before :all do
Rails.application.load_seed
end
end
When in my view_spec I have something like this
require 'spec_helper'
describe 'my/path', type: :view do
before do
#user = create(:user)
#user.permissions << Permission.first
login_as(#user)
visit my_path
end
it 'should have a valid user, just for kicks' do
#user.should be_valid
end
it 'should be in the path i said' do
expect(current_path).to eq(my_path)
end
describe 'click submit button', js: true do
it 'should take me to a different path' do
click_link('button_1')
expect(current_path).to eq(my_new_path)
end
end
end
The first two test will run and be ok with creating that user, but as soon as it hits that last test with js: true, it no longer has Permission in the database.
Is there a way to tell database_cleaner to only delete the data added by rspec? and not the seed?
Or maybe even tell it to not delete certain tables?
Any help would be appreciated.
Try to use :truncation for all tests with:
DatabaseCleaner.strategy = :truncation
RSpec.configure do |config|
config.before(:each) do
DatabaseCleaner.clean
Rails.application.load_seed
end
end
There also may be an issue with your seeds and not with DatabaseCleaner. You should debug your database state right in the failing test using puts statements or debugger (e.g. pry-byebug).

Clear database after testing a rake task using RSpec

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

rspec DatabaseCleaner skip clean for example group metadata tag

How can I tag an example group so that the database isn't cleaned between each example, but is cleaned before and after the whole group? And untagged specs should clean the database between each example.
I would like to write:
describe 'my_dirty_group', :dont_clean do
...
end
So in my spec_helper.rb I put:
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:suite, dont_clean: true) do
DatabaseCleaner.clean
end
config.after(:suite, dont_clean: true) do
DatabaseCleaner.clean
end
config.before(:each, dont_clean: nil) do
DatabaseCleaner.start
end
config.before(:each, dont_clean: nil) do
DatabaseCleaner.clean
end
The problem is that the dont_clean: nil (or false) blocks in spec_helper don't run when the metadata tag is not specified. Is there another way to check for presence of :dont_clean before cleaning between examples?
Summary
You can set custom metadata on the whole example block, and then access the metadata within your RSpec config with self.class.metadata for use with conditional logic.
Code
Using these gem versions:
$ bundle exec gem list | grep -E '^rails |^rspec-core |^database'
database_cleaner (1.4.0)
rails (4.2.0)
rspec-core (3.2.0)
The following works for me:
File: spec/spec_helper.rb
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:all) do
# Clean before each example group if clean_as_group is set
if self.class.metadata[:clean_as_group]
DatabaseCleaner.clean
end
end
config.after(:all) do
# Clean after each example group if clean_as_group is set
if self.class.metadata[:clean_as_group]
DatabaseCleaner.clean
end
end
config.before(:each) do
# Clean before each example unless clean_as_group is set
unless self.class.metadata[:clean_as_group]
DatabaseCleaner.start
end
end
config.after(:each) do
# Clean before each example unless clean_as_group is set
unless self.class.metadata[:clean_as_group]
DatabaseCleaner.clean
end
end
end
File: spec/models/foo_spec.rb
require 'spec_helper'
describe 'a particular resource saved to the database', clean_as_group: true do
it 'should initially be empty' do
expect(Foo.count).to eq(0)
foo = Foo.create()
end
it 'should NOT get cleaned between examples within a group' do
expect(Foo.count).to eq(1)
end
end
describe 'that same resource again' do
it 'should get cleaned between example groups' do
expect(Foo.count).to eq(0)
foo = Foo.create()
end
it 'should get cleaned between examples within a group in the absence of metadata' do
expect(Foo.count).to eq(0)
end
end
You can check on example.metadata inside the blocks, although I haven't been able to figure out how to do this for before(:suite)

Is it possible to add "somewhere" a `before(:each)` hook so that all spec file can run it?

I am using Ruby on Rails 3.2.2 and rspec-rails-2.8.1. In order to make my spec files DRY (Don't Repeat Yourself) and to seed the test database I would like to run a before(:each) hook for all those spec files. That is, in all my spec files I have the following code:
describe 'test description' do
before(:each) do
load "#{Rails.root}/db/seeds.rb"
end
...
end
Is it possible to add "somewhere" that before(:each) hook so that all spec files can run it? What do you advice?
In the spec_helper.rb:
RSpec.configure do |config|
#your other config
config.before(:each) do
#your code here
end
end
There is much configuration available. For instance: config.before(:each, :type => [:routing, :controller, :request])
You can even create your own tags and associate code to it:
config.around :each, unobstrusive: true do |example|
Capybara.current_driver = :rack_test
example.run
Capybara.current_driver = :selenium
end
You can add before/after hooks in your Rspec.configure block, usually in your spec_helper:
RSpec.configure do |config|
config.before(:each) do
...
end
end

Resources