Jak automatycznie załadować db: seed data do testowej bazy danych?

122

Próbuję użyć nowego standardowego sposobu ładowania danych początkowych w Railsach 2.3.4+, db:seedzadaniu rake.

Ładuję stałe dane, które są wymagane, aby moja aplikacja naprawdę działała poprawnie.

Jaki jest najlepszy sposób uruchomienia db:seedzadania przed testami, aby dane zostały wstępnie wypełnione?

Luke Francl
źródło

Odpowiedzi:

120

db:seedZadaniem natarcia głównie właśnie ładuje db/seeds.rbskrypt. Dlatego po prostu wykonaj ten plik, aby załadować dane.

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

# or

Rails.application.load_seed

Gdzie to umieścić, zależy od używanego frameworka testowego i czy chcesz, aby był ładowany przed każdym testem, czy tylko raz na początku. Możesz umieścić to w setuprozmowie lub w test_helper.rbpliku.

ryanb
źródło
4
Uwielbiam prostotę, ale z jakiegoś powodu dodanie tej linii do mojej test_helper.rbnie zadziałało, chociaż stackoverflow.com/a/1998520/68210 tak.
Daniel X Moore
37
W nowszych wersjach szyn możesz to zrobić: Rails.application.load_seed
Steve
@Steve dziękuję - czy wiesz, gdzie umieścić Rails.application.load_seed, jeśli na przykład używa się rspec / capybarra?
BKSpurgeon
1
@BKSpurgeon Ładuję dane początkowe dość często w moich aplikacjach, ponieważ wymagają one określonych danych do uruchomienia, a fabryka jest po prostu zbyt skomplikowana. I umieścić Rails.application.load_seedtuż pod require 'rspec/rails' moim pliku rails_helper. Jeśli używasz klejnotu database_cleaner - będzie to wymagało drobnych poprawek, aby upewnić się, że nie stracisz danych z nasion po każdym teście i możesz to znaleźć w dokumentacji gem it self
MageeWorld
W Railsach 5.x dodałem to test/test_helper.rbpo istniejącej require 'rails/test_help'linii
Andrew
87

Powiedziałbym, że tak powinno być

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

Ponieważ db: test: load nie jest wykonywany, jeśli masz config.active_record.schema_format =: sql (db: test: clone_structure to)

Eugene Bolshakov
źródło
4
Uruchomienie rake z --tracepomogło mi zrozumieć, jak to działa.
Jared Beck
4
@BookOfGreg Mam to w lib / task / test_seed.rake, które stworzyłem sam
Eugene Bolshakov
6
Dlaczego nie tylko to? task 'db:test:prepare' => 'db:seed'
Carson Reinke
3
Dla Rails 4.0.0 ostateczne dodanie ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])przedRake::Task["db:seed"].invoke
janic_
3
@CarsonReinke - bo wtedy środowisko po db:seeduruchomieniu jest development... dziwne.
denishaskin
17

Umieszczenie czegoś takiego w lib / task / test_seed.rake powinno wywołać zadanie seed po db: test: load:

namespace :db do
  namespace :test do
    task :load => :environment do
      Rake::Task["db:seed"].invoke
    end
  end
end
Nick M.
źródło
15

Uważam, że powyższy komentarz Steve'a powinien być poprawną odpowiedzią. Możesz użyć Rails.application.load_seeddo załadowania danych nasion do środowiska testowego. Jednak to, kiedy i jak często te dane są ładowane, zależy od kilku rzeczy:

Korzystanie z programu Minitest

Nie ma wygodnego sposobu na jednorazowe uruchomienie tego pliku przed wszystkimi testami (zobacz ten problem na Githubie ). Będziesz musiał załadować dane raz przed każdym testem, prawdopodobnie w metodzie konfiguracji plików testowych:

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

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

Korzystanie z RSpec

Użyj before(:all)metody RSpec, aby załadować dane początkowe dla wszystkich testów dla tego modelu:

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

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

Mam nadzieję że to pomoże.

Matt
źródło
2
Najlepsza jak dotąd odpowiedź
Yuri Ghensev
Robię coś podobnego, z tym wyjątkiem, że wywołuję to before(:suite)zamiast before(:all). Wysłałem osobną odpowiedź zawierającą sformatowany kod.
Mark Schneider
3

Wywołujemy db: seed jako część db: test: ready, z:

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

W ten sposób dane początkowe są ładowane raz na cały przebieg testu, a nie raz na klasę testową.

jondahl
źródło
4
Czy utworzyłeś nową bazę danych: test: przygotuj zadanie, aby to zrobić? Czy możesz wysłać kod?
Luke Francl
3

Dla tych, którzy używają banku nasion, zmienia sposób ładowania nasion, więc prawdopodobnie nie możesz / nie chcesz korzystać z load ...rozwiązania przedstawionego tutaj.

Rake::Task['db:seed'].invokeSamo wprowadzenie do test_helper zaowocowało:

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

Ale kiedy dodaliśmy wcześniej load_tasks, zadziałało:

MyApp::Application.load_tasks
Rake::Task['db:seed'].invoke
Gary S. Weaver
źródło
2

Dodawanie Rake::Task["db:seed"].invokedo db:test:preparezadania prowizji nie działa dla mnie. Jeśli przygotowałem bazę danych za pomocą rake db:test:prepare, a następnie wszedłem do konsoli w środowisku testowym, wszystkie moje nasiona były tam. Jednak nasiona nie przetrwały między moimi testami.

Dodanie load "#{Rails.root}/db/seeds.rb"do mojej metody konfiguracji działało jednak dobrze.

Chciałbym, aby te nasiona ładowały się automatycznie i utrzymywały się, ale nie znalazłem jeszcze sposobu, aby to zrobić!

alexpls
źródło
0

Opierając się na odpowiedź Matta, jeśli przy tego rodzaju trasy, polecam dzwoniąc Rails.application.load_seedw before(:suite)bloku w rspec_helper.rbzamiast w before(:all)bloku w każdym pliku. W ten sposób kod inicjujący jest wywoływany tylko raz dla całego zestawu testów, a nie raz dla każdej grupy testów.

rspec_helper.rb:

RSpec.configure do |config|
  ...
  config.before(:suite) do
    Rails.application.load_seed
  end
  ...
end
Mark Schneider
źródło