Rails, быть приятелем и reset базой данных между наборами тестов
Работа переходит от Rails 3 к Rails 4. Все, кажется, работает более или менее плавно на стороне разработки, но результаты тестирования приводят к множеству различных сбоев, когда все пакеты - модули, функции и интеграция - запускаются в один идет с rake:test
.
Интересно, что запуск каждого из этих наборов индивидуально не приводит к сбоям. Это наводит на мысль, что база данных не перезагружается для наших тестов в Rails 4 так, как это было в Rails 3.
Я пробовал переопределить rake: test task выполнить db:test:prepare
до запуска каждого пакета, но это, по-видимому, не делает то, что я думаю, что он делает, или, скорее, то, что я хочу, чтобы это сделать, что работать со свежим набором данных для каждого теста и, следовательно, успешно или неудачно независимо от каждого другого теста - способом, которым он был (был или должен был быть) в нашей настройке Rails 3.
Почему это происходит? Как я могу это исправить?
(Обратите внимание, что платформа тестирования - это ванильные Rails с приспособлениями и т.д. Попытки тестирования, которые мы получаем, обычно представляют собой ошибки внешнего ключа или сбои в том, что данные изменяются ожидаемыми способами, которые не отображаются, когда БД reset перед набором для тестирования.)
EDIT:
Вот изменения, которые я делаю в своем Rakefile. Идея состоит в том, чтобы получить rake: test для выполнения, как это было бы в Rails 3, за исключением правильного сброса базы данных между модульными, функциональными и интеграционными пакетами.
# /Rakefile
task :test => [];
Rake::Task[:test].clear
task :test do
puts Rails.env
if Rails.env == "test"
puts "units"
# Rake::Task["db:drop"].execute - results in 'test database not configured' error
# Rake::Task["db:reset"].execute - results in 'relation 'table' does not exist' error
Rake::Task["db:create"].execute
Rake::Task["db:migrate"].execute
Rake::Task["test:units"].execute
puts "functionals"
Rake::Task["db:schema:load"].execute
Rake::Task["test:functionals"].execute
puts "integration"
Rake::Task["db:schema:load"].execute
Rake::Task["test:integration"].execute
end
end
ИЗМЕНИТЬ 2:
Rails версия 4.1.8
Вот мой test_helper. Я опустил вспомогательные методы, которые не работают с нашими данными, поскольку мне, вероятно, не разрешено их распространять, и они не имеют отношения к загрузке базы данных тестирования.
Обратите также внимание на то, что у нас есть пользовательский schema.rb, из которого генерируются данные тестирования, так как попытка создать их из миграций не поддерживает некоторые пользовательские функции/поведение, которые мы хотим в конечном продукте, например, материализованные Просмотры. Обработанный материал будет заключен в < lt; → .
#test_helper.rb
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
include ActionDispatch::TestProcess
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
set_fixture_class <<cached_object>>: ResultsDb::<<DesiredObjectClass>>Cache
fixtures :all
# Add more helper methods to be used by all tests here...
def reload_contig(contig_sym)
contig = contigs(contig_sym)
src = contig.src
new_tig = Contig.new(
org: contig.org,
version: contig.version,
size: contig.size,
sha1: contig.sha1,
active: contig.active,
src_id: src.id,
src_type: contig.src_type)
new_tig.id = contig.id
contig.destroy
unless new_tig.save
raise new_tig.errors.full_messages.inspect
end
src.contigs << new_tig
src.save
new_tig
end
def reload_coord(coord_sym)
coord = coords(coord_sym)
new_coord = Coord.new(
:mapped_id => coord.mapped_id,
:mapped_type => coord.mapped_type,
:contig_id => coord.contig_id,
:contig_type => coord.contig_type,
:start => coord.start,
:stop => coord.stop,
:fwd_strand => coord.fwd_strand
)
new_coord.id = coord.id
coord.destroy
new_coord.save!
end
end
Ответы
Ответ 1
Возможно, вы посмотрите на DatabaseCleaner gem, который специально разработан для обеспечения согласованности и чистоты базы данных во время тестирования в Rails.
У меня возникают проблемы, когда мой код обходит ActiveRecord и напрямую манипулирует данными. Во всех остальных случаях этот камень хорошо работал у меня для тестирования.
Ответ 2
Предполагая, что вы в настоящее время находитесь на Rails 4.0, ваш текущий подход - это лучшее, что вы можете сделать, если вы не можете добавить драгоценный камень database_cleaner. (Я бы предположил, что вы предпочитаете от db:schema:load
до db:migrate
повсюду - нет причин когда-либо запускать все миграции с самого начала в тестовой среде, если вы не сделали с ними что-то необычное). Но как только вы доберетесь до Rails 4.1 или выше, у вас есть лучшее решение.
Начиная с Rails 4.1, автоматизирована схема тестовой базы данных, а rake db:test:prepare
устарела. Если вы обновите test_helper.rb в этот момент, все должно работать магически.
Ответ 3
Вы пытались добавить одно из этих значений при переопределении rake:test
?
rake db:reset db:migrate
или
rake db:drop db:create db:migrate
Вопрос кажется похожим на этот. Я знаю, что всегда создавал свой собственный rake db:recreate
, который делает такие вещи для тестовых данных.