如何自动将db:seed数据加载到测试数据库中?


122

我正在尝试使用新的标准方法在db:seedrake 2.3.4+中的rake任务中加载种子数据。

我正在加载常量数据,这是我的应用程序真正正常运行所必需的。

使db:seed任务在测试之前运行的最佳方法是什么,以便预先填充数据?

Answers:


120

db:seedrake任务主要只是用来加载db/seeds.rb脚本。因此,只需执行该文件即可加载数据。

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

# or

Rails.application.load_seed

放置在何处取决于您使用的是什么测试框架,以及是否希望在每次测试之前或在开始时仅一次加载它。您可以将其放入setup通话或test_helper.rb文件中。


4
我喜欢这种简单性,但是出于某种原因test_helper.rb,尽管stackoverflow.com/a/1998520/68210可以,但添加此行对我却不起作用。
Daniel X Moore

37
在新版本的Rails中,您可以执行以下操作:Rails.application.load_seed
Steve

@Steve谢谢-例如,如果您正在使用rspec / capybarra,您知道将Rails.application.load_seed放在哪里吗?
BKSpurgeon '16

1
@BKSpurgeon我在我的应用程序中加载了很多种子数据,因为它需要运行特定的数据并且工厂太复杂了。我把Rails.application.load_seed右下require 'rspec/rails' 我rails_helper文件。如果您使用的是database_cleaner gem,则需要进行一些微调以确保每次测试后都不会丢失种子数据,并且可以在gem的文档中找到它本身
MageeWorld,2016年

在Rails 5.x中,我将此添加到test/test_helper.rb现有require 'rails/test_help'行之后
Andrew

87

我会说应该

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

因为如果具有config.active_record.schema_format =:sql,则不会执行db:test:load(db:test:clone_structure是)


4
跑耙--trace帮助我了解了它的工作原理。
贾里德·贝克

4
@BookOfGreg我在创建自己的lib / tasks / test_seed.rake中拥有它
Eugene Bolshakov

6
为什么不只是这个呢? task 'db:test:prepare' => 'db:seed'
卡森·莱因克

3
对于Rails 4.0.0最终添加ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])Rake::Task["db:seed"].invoke
janic_

3
@CarsonReinke-因为那时db:seed运行时的环境很development奇怪。
denishaskin 2013年

17

在lib / tasks / test_seed.rake中放置这样的内容应该在db:test:load之后调用种子任务:

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

15

我相信史蒂夫的上述评论应该是正确的答案。您可以用来Rails.application.load_seed将种子数据加载到测试环境中。但是,何时以及何时加载此数据取决于以下几件事:

使用Minitest

在进行所有测试之前,没有一种方便的方法可以运行一次此文件(请参阅此Github问题)。您可能需要在测试文件的设置方法中,在每次测试之前加载一次数据:

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

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

使用RSpec

使用RSpec的before(:all)方法为该模型的所有测试加载种子数据:

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

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

希望这可以帮助。


2
迄今为止最好的答案
Yuri Ghensev

我做了类似的事情,除了我调用before(:suite)而不是before(:all)。发布一个单独的答案以包含格式化的代码。
Mark Schneider

3

我们正在将db:seed作为db:test:prepare的一部分进行调用,其中包括:

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

这样,种子数据将在整个测试运行中加载一次,而不是每个测试类加载一次。


4
您是否创建了一个新的db:test:prepare任务来做到这一点?您可以发布代码吗?
卢克·弗朗克

3

对于使用种子库的用户,它会更改种子的加载方式,因此您可能希望/不希望使用load ...此处提供的解决方案。

而仅仅放入Rake::Task['db:seed'].invoketest_helper会导致:

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

但是当我们在此之前添加load_tasks时,它起作用了:

MyApp::Application.load_tasks
Rake::Task['db:seed'].invoke

2

添加Rake::Task["db:seed"].invokedb:test:preparerake任务对我不起作用。如果我使用来准备数据库rake db:test:prepare,然后在测试环境中进入控制台,那么我所有的种子都在那里。但是,种子在我的测试之间没有持续存在。

不过,将其添加load "#{Rails.root}/db/seeds.rb"到我的设置方法中效果很好。

我很想让这些种子自动加载并持久保存,但是我还没有找到一种方法来做到这一点!


0

基于Matt的答案,如果采取这种方式,我建议Rails.application.load_seed在一个文件before(:suite)rspec_helper.rb而不是before(:all)任何文件的块中调用。这样,整个测试套件仅调用一次种子代码,而不是为每组测试调用一次。

rspec_helper.rb:

RSpec.configure do |config|
  ...
  config.before(:suite) do
    Rails.application.load_seed
  end
  ...
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.