我正在用RubyonRails 4.2运行minitest。我暂时无法更改框架的版本。我想测试几个地区的邮件操作。因此,我希望在执行所有测试之前进行初始化,并通过FactoryBot在数据库中创建用户。
我只想做一次,而不是之前的所有测试,因为它不具有性能。
这里是我最喜欢的课程:
require 'test_helper'
class PurchaseMailerTest < ActionMailer::TestCase
@@flag = nil
before do
unless @@flag
@@emails = Hash.new
@@buyers = Hash.new
@@sales = Hash.new
I18n.available_locales.each do |locale|
buyer = FactoryBot.create(:buyer, sale_line_items_count: 1, locale: locale)
sale = buyer.orders.first.sales.first
email = PurchaseMailer.accepted(sale.id)
@@emails.store(locale, email)
@@buyers.store(locale, buyer)
@@sales.store(locale, sale)
end
@@flag = true
end
end
I18n.available_locales.each do |locale|
context locale do
it 'test_email_to' do
assert_equal [@@buyers[locale].email], @@emails[locale].to
end
it 'test_email_from' do
assert_equal [ENV['EMAIL']], @@emails[locale].from
end
it 'test_of_subject' do
subject_from_I18n = I18n.t('purchase_mailer.accepted.subject', sale_ref: @@sales[locale].slug, locale: locale)
assert_includes @@emails[locale].subject, subject_from_I18n
end
end
end
end
第一个循环I18n.available_locates是ok,但在第二个循环时,我得到了以下错误:
ActiveRecord::RecordNotFound: ActiveRecord::RecordNotFound: Couldn't find Sale with 'id'=c0925b6a-4b48-4cb5-9120-03be48187dd
在第一个循环期间,我的测试数据库包含所有初始化的数据,在第二个循环中,数据被擦除了,我不知道为什么。
我认为还有更优雅的解决方案,但我希望保持良好的性能,只初始化一次数据。我已经测试了一个基于define_method的解决方案,但问题仍然存在。
有关更多信息,请访问我的test_helper:
ENV['RACK_ENV'] = 'test'
ENV['RAILS_ENV'] = 'test'
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest"
require "minitest/rails"
require 'factory_bot_rails'
require 'minitest-spec-context'
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
end
我找到了一个解决方案,首先在test_helper中创建两个方法:
- 开始通过FactoryBot只执行一次对象创建,性能良好
- 小型测试:数据库清理器的after_run
ENV['RACK_ENV'] = 'test'
ENV['RAILS_ENV'] = 'test'
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest"
require "minitest/rails"
require 'factory_bot_rails'
require 'minitest-spec-context'
require 'database_cleaner'
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
DatabaseCleaner.strategy = :truncation
begin
@@buyers = Hash.new
@@sales = Hash.new
I18n.available_locales.each do |locale|
buyer = FactoryBot.create(:buyer, sale_line_items_count: 1, locale: locale)
@@buyers.store(locale, buyer)
sale = buyer.orders.first.sales.first
@@sales.store(locale, sale)
end
end
Minitest.after_run do
DatabaseCleaner.clean
end
end
PurchaseMailerTest类中解决方案的下一部分是在循环中使用define_method,名称中包含变量locale,而是另一种定义测试方法的样式(rspec样式为'it'或测试方法为'def'(,因为这样就不会再有ActiveRecord错误了。
I18n.available_locales.each do |locale|
define_method :"test_mail_to_#{locale}" do
assert_equal [@@buyers[locale].email], @@emails[locale].to
end
...