Как автоматически загрузить данные db: seed в тестовую базу данных?

122

Я пытаюсь использовать новый стандартный способ загрузки исходных данных в Rails 2.3.4+ - db:seedзадачу rake.

Я загружаю постоянные данные, которые необходимы моему приложению для правильной работы.

Как лучше всего запустить db:seedзадачу перед тестами, чтобы данные были предварительно заполнены?

Люк Франкл
источник

Ответы:

120

Задача db:seedrake в основном просто загружает db/seeds.rbскрипт. Поэтому просто запустите этот файл, чтобы загрузить данные.

load "#{Rails.root}/db/seeds.rb"

# or

Rails.application.load_seed

Где это разместить, зависит от того, какую среду тестирования вы используете, и хотите ли вы, чтобы она загружалась перед каждым тестом или только один раз в начале. Вы можете поместить это в setupзвонок или в test_helper.rbфайл.

ryanb
источник
4
Мне нравится простота, но по какой-то причине добавление этой строки в мою test_helper.rbне сработало для меня, хотя stackoverflow.com/a/1998520/68210 сработал .
Daniel X Moore
37
В более новых версиях rails вы можете: Rails.application.load_seed
Стив,
@Steve, спасибо - знаете ли вы, куда поместить Rails.application.load_seed, если, например, используется rspec / capybarra?
BKSpurgeon
1
@BKSpurgeon Я довольно часто загружаю начальные данные в свои приложения, потому что для их работы требуются определенные данные, а фабрика слишком сложна. Я положил Rails.application.load_seedпрямо require 'rspec/rails' в свой файл rails_helper. Если вы используете гем database_cleaner - потребуется небольшая настройка, чтобы убедиться, что вы не потеряете свои исходные данные после каждого теста, и вы можете найти это в документации на сам гем
MageeWorld
В Rails 5.x я добавил это test/test_helper.rbпосле существующей require 'rails/test_help'строки
Эндрю
87

Я бы сказал, что это должно быть

namespace :db do
  namespace :test do
    task :prepare => :environment do
      Rake::Task["db:seed"].invoke
    end
  end
end

Потому что db: test: load не выполняется, если у вас есть config.active_record.schema_format =: sql (db: test: clone_structure is)

Евгений Большаков
источник
4
Использование граблей --traceпомогло мне понять, как это работает.
Джаред Бек
4
@BookOfGreg У меня он есть в lib / tasks / test_seed.rake, который я создал сам
Евгений Большаков
6
Почему не только это? task 'db:test:prepare' => 'db:seed'
Carson Reinke
3
Для Rails 4.0.0 финальное добавление ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])передRake::Task["db:seed"].invoke
janic_
3
@CarsonReinke - потому что тогда , когда среда db:seedпроходит в development... удачливый.
denishaskin
17

Помещение чего-то подобного в lib / tasks / test_seed.rake должно вызывать начальную задачу после db: test: load:

namespace :db do
  namespace :test do
    task :load => :environment do
      Rake::Task["db:seed"].invoke
    end
  end
end
Ник М
источник
15

Я считаю, что приведенный выше комментарий Стива должен быть правильным ответом. Вы можете использовать его Rails.application.load_seedдля загрузки исходных данных в тестовую среду. Однако то, когда и как часто загружаются эти данные, зависит от нескольких вещей:

Использование Minitest

Нет удобного способа запустить этот файл один раз перед всеми тестами (см. Этот выпуск Github ). Вам нужно будет загружать данные один раз перед каждым тестом, вероятно, в методе настройки ваших тестовых файлов:

# test/models/my_model_test.rb
class LevelTest < ActiveSupport::TestCase

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

Использование RSpec

Используйте before(:all)метод RSpec для загрузки исходных данных для всех тестов для этой модели:

describe MyModel do
  before(:all) do
  Rails.application.load_seed
end

describe "my model..." do
  # your tests here
end

Надеюсь это поможет.

Matt
источник
2
Лучший ответ на данный момент
Юрий Генсев
Я делаю нечто подобное, за исключением того, что вызываю его before(:suite)вместо before(:all). Отправил отдельный ответ, чтобы включить отформатированный код.
Марк Шнайдер
3

Мы вызываем db: seed как часть db: test: prepare с помощью:

Rake::Task["db:seed"].invoke

Таким образом, исходные данные загружаются один раз за весь тестовый прогон, а не один раз за тестовый класс.

jondahl
источник
4
Вы создали для этого новую задачу db: test: prepare? Можете выложить код?
Люк Франкл,
3

Для тех, кто использует банк семян, он меняет способ загрузки семян, поэтому вы, вероятно, не сможете / не захотите использовать load ...предлагаемое здесь решение.

И просто ввод Rake::Task['db:seed'].invokeв test_helper привел к:

Don't know how to build task 'db:seed' (RuntimeError)

Но когда мы добавили load_tasks перед этим, это сработало:

MyApp::Application.load_tasks
Rake::Task['db:seed'].invoke
Гэри С. Уивер
источник
2

Добавление Rake::Task["db:seed"].invokeв db:test:prepareзадачу рейка у меня не получилось. Если я подготовил базу данных с помощью rake db:test:prepare, а затем вошел в консоль в тестовой среде, все мои семена были там. Однако между моими испытаниями семена не сохранялись.

Однако добавление load "#{Rails.root}/db/seeds.rb"к моему методу настройки сработало.

Я бы хотел, чтобы эти семена загружались автоматически и сохранялись, но я еще не нашел способа сделать это!

alexpls
источник
0

Основываясь на ответе Мэтта, если вы выберете такой маршрут, я рекомендую звонить Rails.application.load_seedв before(:suite)блок, rspec_helper.rbа не вbefore(:all) блоке в любом файле. Таким образом, код заполнения вызывается только один раз для всего набора тестов, а не один раз для каждой группы тестов.

rspec_helper.rb:

RSpec.configure do |config|
  ...
  config.before(:suite) do
    Rails.application.load_seed
  end
  ...
end
Марк Шнайдер
источник