Wie lade ich db: seed-Daten automatisch in die Testdatenbank?

122

Ich versuche, die neue Standardmethode zum Laden von Seed-Daten in Rails 2.3.4+, der db:seedRake-Aufgabe, zu verwenden.

Ich lade konstante Daten, die erforderlich sind, damit meine Anwendung wirklich richtig funktioniert.

Was ist der beste Weg, um die db:seedAufgabe vor den Tests auszuführen, damit die Daten vorab ausgefüllt werden?

Luke Francl
quelle

Antworten:

120

Die db:seedRechenaufgabe lädt in erster Linie nur das db/seeds.rbSkript. Führen Sie daher einfach diese Datei aus, um die Daten zu laden.

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

# or

Rails.application.load_seed

Wo dies platziert werden soll, hängt davon ab, welches Testframework Sie verwenden und ob es vor jedem Test oder nur einmal zu Beginn geladen werden soll. Sie können es in einen setupAnruf oder in eine test_helper.rbDatei einfügen.

Ryanb
quelle
4
Ich mag die Einfachheit, aber aus irgendeinem Grund hat das Hinzufügen dieser Zeile zu meiner test_helper.rbnicht funktioniert, obwohl stackoverflow.com/a/1998520/68210 dies tat.
Daniel X Moore
37
In neueren Versionen von Rails können Sie Folgendes tun: Rails.application.load_seed
Steve
@Steve danke - wissen Sie, wo Sie Rails.application.load_seed ablegen sollen, wenn Sie beispielsweise rspec / capybarra verwenden?
BKSpurgeon
1
@BKSpurgeon Ich lade häufig Startdaten in meine Anwendungen, da für die Ausführung bestimmte Daten erforderlich sind und die Factory einfach zu kompliziert ist. Ich habe Rails.application.load_seeddirekt require 'rspec/rails' in meine Datei rails_helper eingefügt. Wenn Sie database_cleaner gem verwenden, müssen Sie einige Anpassungen vornehmen, um sicherzustellen, dass Sie Ihre Seed-Daten nicht nach jedem Test verlieren.
Dies
In Rails 5.x habe ich dies test/test_helper.rbnach der bestehenden require 'rails/test_help'Zeile hinzugefügt
Andrew
87

Ich würde sagen, es sollte sein

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

Weil db: test: load nicht ausgeführt wird, wenn Sie config.active_record.schema_format =: sql haben (db: test: clone_structure ist)

Eugene Bolshakov
quelle
4
Das Laufen mit Rake --tracehalf mir zu verstehen, wie das funktioniert.
Jared Beck
4
@BookOfGreg Ich habe es in lib / task / test_seed.rake, dass ich mich selbst erstellt habe
Eugene Bolshakov
6
Warum nicht einfach das? task 'db:test:prepare' => 'db:seed'
Carson Reinke
3
Für Rails 4.0.0 final add ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])beforeRake::Task["db:seed"].invoke
janic_
3
@CarsonReinke - weil dann die Umgebung , wenn db:seedläuft ist development... bizarr.
Denishaskin
17

Wenn Sie so etwas in lib / task / test_seed.rake einfügen, sollte die Startaufgabe nach db: test: load: aufgerufen werden.

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

Ich glaube, Steves Kommentar oben sollte die richtige Antwort sein. Sie können Rails.application.load_seeddamit Seed-Daten in Ihre Testumgebung laden. Wann und wie oft diese Daten geladen werden, hängt jedoch von einigen Faktoren ab:

Verwenden von Minitest

Es gibt keine bequeme Möglichkeit, diese Datei vor allen Tests einmal auszuführen (siehe dieses Github-Problem ). Sie müssen die Daten vor jedem Test einmal laden, wahrscheinlich in der Setup-Methode Ihrer Testdateien:

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

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

RSpec verwenden

Verwenden Sie die RSpec- before(:all)Methode, um Startdaten für alle Tests für dieses Modell zu laden:

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

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

Hoffe das hilft.

Matt
quelle
2
Beste Antwort bisher
Yuri Ghensev
Ich mache etwas Ähnliches, außer dass ich es before(:suite)anstelle von aufrufe before(:all). Veröffentlichte eine separate Antwort mit formatiertem Code.
Mark Schneider
3

Wir rufen db: seed als Teil von db: test: prepare auf, mit:

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

Auf diese Weise werden die Startdaten einmal für den gesamten Testlauf und nicht einmal pro Testklasse geladen.

jondahl
quelle
4
Haben Sie eine neue Datenbank erstellt: test: Bereiten Sie die Aufgabe dafür vor? Können Sie den Code posten?
Luke Francl
3

Für diejenigen, die eine Samenbank verwenden, ändert sich die Art und Weise, wie Samen geladen werden, sodass Sie load ...die hier bereitgestellte Lösung wahrscheinlich nicht verwenden können / wollen .

Und nur das Rake::Task['db:seed'].invokeEinfügen in test_helper führte zu:

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

Aber als wir zuvor load_tasks hinzugefügt haben, hat es funktioniert:

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

Das Hinzufügen Rake::Task["db:seed"].invokezur db:test:prepareRechenaufgabe hat bei mir nicht funktioniert. Wenn ich die Datenbank mit vorbereitet rake db:test:prepareund dann die Konsole in der Testumgebung aufgerufen habe, waren alle meine Seeds vorhanden. Die Samen blieben jedoch zwischen meinen Tests nicht bestehen.

Das Hinzufügen load "#{Rails.root}/db/seeds.rb"zu meiner Setup-Methode hat jedoch gut funktioniert.

Ich würde gerne diese Samen automatisch laden und bestehen lassen, aber ich habe noch keinen Weg gefunden, dies zu tun!

alexpls
quelle
0

Aufbauend auf Matts Antwort empfehle ich, wenn Sie diese Art von Route wählen, Rails.application.load_seedeinen before(:suite)Block in rspec_helper.rbund nicht einen before(:all)Block in einer Datei aufzurufen . Auf diese Weise wird der Seeding-Code nur einmal für die gesamte Testsuite und nicht einmal für jede Testgruppe aufgerufen.

rspec_helper.rb:

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