¿Cómo cargar datos db: seed en la base de datos de prueba automáticamente?

122

Estoy intentando utilizar la nueva forma estándar de cargar datos semilla en Rails 2.3.4+, el db:seed tarea de rastrillo.

Estoy cargando datos constantes, que son necesarios para que mi aplicación realmente funcione correctamente.

¿Cuál es la mejor manera de db:seedejecutar la tarea antes de las pruebas, para que los datos se completen previamente?

Luke Francl
fuente

Respuestas:

120

La db:seedtarea de rake principalmente solo carga el db/seeds.rbscript. Por lo tanto, simplemente ejecute ese archivo para cargar los datos.

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

# or

Rails.application.load_seed

Dónde ubicar eso depende de qué marco de prueba está utilizando y si desea que se cargue antes de cada prueba o solo una vez al principio. Puede ponerlo en una setupllamada o en un test_helper.rbarchivo.

ryanb
fuente
44
Me encanta la simplicidad, pero por alguna razón agregar esta línea a mi test_helper.rbno funcionó para mí, aunque stackoverflow.com/a/1998520/68210 sí.
Daniel X Moore
37
En las versiones más nuevas de rails puedes hacer: Rails.application.load_seed
Steve
@ Steve gracias, ¿sabe dónde colocar Rails.application.load_seed si uno está usando rspec / capybarra, por ejemplo?
BKSpurgeon
1
@BKSpurgeon Cargo bastante información inicial en mis aplicaciones porque requiere datos específicos para ejecutarse y la fábrica es demasiado complicada. Puse Rails.application.load_seedjusto debajo require 'rspec/rails' de mi archivo rails_helper. Si está utilizando database_cleaner gem, requerirá un pequeño ajuste para asegurarse de que no pierda sus datos de semilla después de cada prueba y puede encontrarlo en la documentación de la gema en sí misma
MageeWorld
En Rails 5.x agregué esto test/test_helper.rbdespués de la require 'rails/test_help'línea existente
Andrew
87

Yo diría que debería ser

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

Porque db: test: load no se ejecuta si tiene config.active_record.schema_format =: sql (db: test: clone_structure is)

Eugene Bolshakov
fuente
44
Running rake with --traceme ayudó a entender cómo funciona esto.
Jared Beck
44
@BookOfGreg Lo tengo en lib / task / test_seed.rake que yo mismo creé
Eugene Bolshakov
66
¿Por qué no solo esto? task 'db:test:prepare' => 'db:seed'
Carson Reinke
3
Para Rails 4.0.0 final agregar ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])antesRake::Task["db:seed"].invoke
janic_
3
@CarsonReinke, porque entonces el entorno cuando se db:seedejecuta es development... extraño.
denishaskin
17

Poner algo como esto en lib / task / test_seed.rake debería invocar la tarea inicial después de db: test: load:

namespace :db do
  namespace :test do
    task :load => :environment do
      Rake::Task["db:seed"].invoke
    end
  end
end
Nick M
fuente
15

Creo que el comentario anterior de Steve debería ser la respuesta correcta. Puede usar Rails.application.load_seedpara cargar datos de inicialización en su entorno de prueba. Sin embargo, cuándo y con qué frecuencia se cargan estos datos depende de algunas cosas:

Usando Minitest

No hay una forma conveniente de ejecutar este archivo una vez antes de todas las pruebas (vea este problema de Github ). Deberá cargar los datos una vez antes de cada prueba, probablemente en el método de configuración de sus archivos de prueba:

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

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

Usando RSpec

Utilice el before(:all)método de RSpec para cargar datos de inicialización para todas las pruebas para este modelo:

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

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

Espero que esto ayude.

Mate
fuente
2
La mejor respuesta hasta ahora
Yuri Ghensev
Hago algo similar, excepto que lo invoco en before(:suite)lugar de hacerlo before(:all). Publicó una respuesta separada para incluir código formateado.
Mark Schneider
3

Invocamos db: seed como parte de db: test: prepare, con:

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

De esa forma, los datos de inicialización se cargan una vez para toda la ejecución de prueba, y no una vez por clase de prueba.

jondahl
fuente
44
¿Creó un nuevo db: test: prepare la tarea para hacer eso? ¿Puedes publicar el código?
Luke Francl
3

Para aquellos que usan el banco de semillas, cambia la forma en que se cargan las semillas, por lo que probablemente no pueda / no quiera usar la load ...solución provista aquí.

Y solo poner Rake::Task['db:seed'].invokeen test_helper resultó en:

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

Pero cuando agregamos load_tasks antes de eso, funcionó:

MyApp::Application.load_tasks
Rake::Task['db:seed'].invoke
Gary S. Weaver
fuente
2

Agregar Rake::Task["db:seed"].invokea la db:test:preparetarea de rastrillo no funcionó para mí. Si preparé la base de datos con rake db:test:prepare, y luego ingresé a la consola dentro del entorno de prueba, todas mis semillas estaban allí. Sin embargo, las semillas no persistieron entre mis pruebas.

Sin load "#{Rails.root}/db/seeds.rb"embargo, agregar a mi método de configuración funcionó bien.

Me encantaría que estas semillas se cargaran automáticamente y persistieran, ¡pero todavía no he encontrado la manera de hacerlo!

alexpls
fuente
0

Sobre la base de la respuesta de Matt, si toma ese tipo de ruta, recomiendo llamar Rails.application.load_seeden un before(:suite)bloque en rspec_helper.rblugar de en unbefore(:all) bloque en cualquier archivo. De esta forma, el código inicial se invoca solo una vez para todo el conjunto de pruebas en lugar de una vez para cada grupo de pruebas.

rspec_helper.rb:

RSpec.configure do |config|
  ...
  config.before(:suite) do
    Rails.application.load_seed
  end
  ...
end
Mark Schneider
fuente