Comment charger automatiquement les données db: seed dans la base de données de test?

122

J'essaie d'utiliser la nouvelle méthode standard de chargement des données de départ dans Rails 2.3.4+, la db:seedtâche rake.

Je charge des données constantes, nécessaires au bon fonctionnement de mon application.

Quelle est la meilleure façon d' db:seedexécuter la tâche avant les tests, afin que les données soient préremplies?

Luc Francl
la source

Réponses:

120

La db:seedtâche rake ne charge principalement que le db/seeds.rbscript. Par conséquent, exécutez simplement ce fichier pour charger les données.

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

# or

Rails.application.load_seed

Où placer cela dépend du framework de test que vous utilisez et si vous voulez qu'il soit chargé avant chaque test ou juste une fois au début. Vous pouvez le mettre dans un setupappel ou dans un test_helper.rbfichier.

Ryanb
la source
4
J'adore la simplicité, mais pour une raison quelconque, l'ajout de cette ligne à mon test_helper.rbn'a pas fonctionné pour moi bien que stackoverflow.com/a/1998520/68210 l'ait fait.
Daniel X Moore le
37
Dans les nouvelles versions de rails, vous pouvez faire: Rails.application.load_seed
Steve
@Steve merci - savez-vous où mettre Rails.application.load_seed si l'on utilise rspec / capybarra, par exemple?
BKSpurgeon
1
@BKSpurgeon Je charge un peu les données de départ dans mes applications car elles nécessitent des données spécifiques pour fonctionner et l'usine est tout simplement trop compliquée. J'ai mis Rails.application.load_seedjuste en dessous require 'rspec/rails' dans mon fichier rails_helper. Si vous utilisez la gemme database_cleaner - il faudra quelques ajustements pour vous assurer de ne pas perdre vos données de départ après chaque test et vous pouvez le trouver dans la documentation de la gemme elle-même
MageeWorld
Dans Rails 5.x, j'ai ajouté ceci test/test_helper.rbaprès la require 'rails/test_help'ligne existante
Andrew
87

Je dirais que ça devrait être

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

Parce que db: test: load n'est pas exécuté si vous avez config.active_record.schema_format =: sql (db: test: clone_structure is)

Eugène Bolshakov
la source
4
L'exécution de rake avec --tracem'a aidé à comprendre comment cela fonctionne.
Jared Beck
4
@BookOfGreg Je l'ai dans lib / tasks / test_seed.rake que j'ai créé moi
Eugene Bolshakov
6
Pourquoi pas juste ça? task 'db:test:prepare' => 'db:seed'
Carson Reinke
3
Pour Rails 4.0.0 final ajouter ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])avantRake::Task["db:seed"].invoke
janic_
3
@CarsonReinke - parce qu'alors, l'environnement lors de l' db:seedexécution est development... bizarre.
denishaskin
17

Mettre quelque chose comme ça dans lib / tasks / test_seed.rake devrait appeler la tâche d'amorçage après db: test: load:

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

Je crois que le commentaire de Steve ci-dessus devrait être la bonne réponse. Vous pouvez utiliser Rails.application.load_seedpour charger des données d'amorçage dans votre environnement de test. Cependant, le moment et la fréquence de chargement de ces données dépendent de plusieurs facteurs:

Utilisation de Minitest

Il n'y a pas de moyen pratique d'exécuter ce fichier une fois avant tous les tests (voir ce problème Github ). Vous devrez charger les données une fois avant chaque test, probablement dans la méthode de configuration de vos fichiers de test:

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

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

Utilisation de RSpec

Utilisez la before(:all)méthode de RSpec pour charger les données de départ pour tous les tests de ce modèle:

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

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

J'espère que cela t'aides.

Mat
la source
2
Meilleure réponse à ce jour
Yuri Ghensev
Je fais quelque chose de similaire, sauf que je l'invoque au before(:suite)lieu de before(:all). Publié une réponse distincte pour inclure le code formaté.
Mark Schneider
3

Nous invoquons db: seed dans le cadre de db: test: prepare, avec:

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

De cette façon, les données de départ sont chargées une fois pendant toute la durée du test, et non une fois par classe de test.

Jondahl
la source
4
Avez-vous créé une nouvelle tâche db: test: prepare pour faire cela? Pouvez-vous poster le code?
Luke Francl
3

Pour ceux qui utilisent la banque de graines, cela change la façon dont les graines sont chargées, donc vous ne pouvez / ne voulez probablement pas utiliser la load ...solution fournie ici.

Et simplement mettre Rake::Task['db:seed'].invokedans test_helper a abouti à:

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

Mais quand nous avons ajouté load_tasks avant cela, cela fonctionnait:

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

L'ajout Rake::Task["db:seed"].invokede la db:test:preparetâche de râteau n'a pas fonctionné pour moi. Si j'ai préparé la base de données avec rake db:test:prepare, puis entré dans la console dans l'environnement de test, toutes mes graines étaient là. Cependant, les graines n'ont pas persisté entre mes tests.

L'ajout load "#{Rails.root}/db/seeds.rb"à ma méthode de configuration a bien fonctionné, cependant.

J'adorerais que ces graines se chargent automatiquement et persistent, mais je n'ai pas encore trouvé de moyen de le faire!

alexpls
la source
0

S'appuyant sur la réponse de Matt, si vous empruntez ce genre de route, je recommande d'appeler Rails.application.load_seedun before(:suite)bloc rspec_helper.rbplutôt que dans unbefore(:all) bloc dans n'importe quel fichier. De cette façon, le code d'amorçage est appelé une seule fois pour toute la suite de tests plutôt qu'une fois pour chaque groupe de tests.

rspec_helper.rb:

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