Como carregar dados do db: seed no banco de dados de teste automaticamente?

122

Estou tentando usar a nova maneira padrão de carregar dados de propagação no Rails 2.3.4+, a db:seedtarefa rake.

Estou carregando dados constantes, necessários para que meu aplicativo realmente funcione corretamente.

Qual é a melhor maneira de executar a db:seedtarefa antes dos testes, para que os dados sejam preenchidos previamente?

Luke Francl
fonte

Respostas:

120

A db:seedtarefa de rake carrega principalmente o db/seeds.rbscript. Portanto, basta executar esse arquivo para carregar os dados.

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

# or

Rails.application.load_seed

Onde colocar isso depende de qual estrutura de teste você está usando e se deseja que ela seja carregada antes de cada teste ou apenas uma vez no início. Você pode colocá-lo em uma setupchamada ou em um test_helper.rbarquivo.

ryanb
fonte
4
Eu amo a simplicidade, mas, por algum motivo, adicionar essa linha à minha test_helper.rbnão funcionou para mim, apesar do stackoverflow.com/a/1998520/68210 .
Daniel X Moore
37
Em versões mais recentes de trilhos que você pode fazer: Rails.application.load_seed
Steve
@ Steve obrigado - você sabe onde colocar Rails.application.load_seed se alguém estiver usando rspec / capybarra, por exemplo?
BKSpurgeon
1
@BKSpurgeon Carrego dados de sementes bastante em meus aplicativos porque requer dados específicos para execução e a fábrica é muito complicada. Coloquei Rails.application.load_seedlogo abaixo require 'rspec/rails' no meu arquivo rails_helper. Se você estiver usando database_cleaner jóia - ela vai exigir um pouco de ajustes para se certificar de que você não perca seus dados de sementes depois de cada teste e você pode descobrir que na documentação da gema auto
MageeWorld
No Rails 5.x I adicionou isto test/test_helper.rbapós a existente require 'rails/test_help'linha
Andrew
87

Eu diria que deveria ser

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

Como o db: test: load não será executado se você tiver config.active_record.schema_format =: sql (db: test: clone_structure is)

Eugene Bolshakov
fonte
4
A execução do rake --traceajudou-me a entender como isso funciona.
Jared Beck
4
@BookOfGreg eu tê-lo em lib / tarefas / test_seed.rake que eu mesmo criei
Eugene Bolshakov
6
Por que não apenas isso? task 'db:test:prepare' => 'db:seed'
Carson Reinke
3
Para finalizar o Rails 4.0.0, adicione ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])antesRake::Task["db:seed"].invoke
janic_
3
@CarsonReinke - porque então o ambiente quando db:seedé executado é development... estranhamente.
Denishaskin # 13/13
17

Colocar algo parecido com isto em lib / tasks / test_seed.rake deve chamar a tarefa seed após db: test: load:

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

Acredito que o comentário de Steve acima deve ser a resposta correta. Você pode usar Rails.application.load_seedpara carregar dados de sementes no ambiente de teste. No entanto, quando e com que frequência esses dados são carregados depende de algumas coisas:

Usando o Minitest

Não há uma maneira conveniente de executar esse arquivo uma vez antes de todos os testes (consulte este problema no Github ). Você precisará carregar os dados uma vez antes de cada teste, provavelmente no método de configuração dos seus arquivos de teste:

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

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

Usando o RSpec

Use o before(:all)método do RSpec para carregar dados iniciais para todos os testes deste modelo:

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

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

Espero que isto ajude.

Matt
fonte
2
Melhor resposta até agora
Yuri Ghensev
Faço algo semelhante, exceto que estou invocando em before(:suite)vez de before(:all). Publicou uma resposta separada para incluir código formatado.
Mark Schneider
3

Estamos invocando db: seed como parte do db: test: prepare, com:

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

Dessa forma, os dados iniciais são carregados uma vez durante toda a execução do teste e não uma vez por classe de teste.

jondahl
fonte
4
Você criou uma nova tarefa db: test: prepare para fazer isso? Você pode postar o código?
31510 Luke Francl
3

Para aqueles que usam o banco de sementes, isso altera a maneira como as sementes são carregadas, portanto você provavelmente não pode / não deseja usar a load ...solução fornecida aqui.

E apenas colocar Rake::Task['db:seed'].invoketest_helper resultou em:

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

Mas quando adicionamos load_tasks antes disso, funcionou:

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

Adicionando Rake::Task["db:seed"].invokeà db:test:preparetarefa rake não funcionou para mim. Se eu preparei o banco de dados rake db:test:preparee entrei no console no ambiente de teste, todas as minhas sementes estavam lá. No entanto, as sementes não persistiram entre os meus testes.

Adicionando load "#{Rails.root}/db/seeds.rb"ao meu método de instalação funcionou bem, no entanto.

Gostaria muito que essas sementes carregassem automaticamente e persistissem, mas ainda não encontrei uma maneira de fazer isso!

alexpls
fonte
0

Com base na resposta de Matt, se você seguir esse tipo de rota, recomendo chamar Rails.application.load_seedum before(:suite)bloco em rspec_helper.rbvez de um before(:all)bloco em qualquer arquivo. Dessa forma, o código de propagação é chamado apenas uma vez para todo o conjunto de testes e não uma vez para cada grupo de testes.

rspec_helper.rb:

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