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, который делает такие вещи для тестовых данных.