【发布时间】:2010-12-07 04:24:33
【问题描述】:
我正在尝试使用在 Rails 2.3.4+ 中加载种子数据的新标准方法,db:seed rake 任务。
我正在加载常量数据,这是我的应用程序真正正常运行所必需的。
在测试之前让db:seed 任务运行的最佳方法是什么,以便预先填充数据?
【问题讨论】:
标签: ruby-on-rails testing seed
我正在尝试使用在 Rails 2.3.4+ 中加载种子数据的新标准方法,db:seed rake 任务。
我正在加载常量数据,这是我的应用程序真正正常运行所必需的。
在测试之前让db:seed 任务运行的最佳方法是什么,以便预先填充数据?
【问题讨论】:
标签: ruby-on-rails testing seed
db:seed rake 任务主要只是加载db/seeds.rb 脚本。因此只需执行该文件即可加载数据。
load "#{Rails.root}/db/seeds.rb"
# or
Rails.application.load_seed
放置位置取决于您使用的测试框架以及您是希望在每次测试之前加载它还是只在开始时加载一次。您可以将其放入setup 调用或test_helper.rb 文件中。
【讨论】:
test_helper.rb 对我不起作用,尽管 stackoverflow.com/a/1998520/68210 确实如此。
Rails.application.load_seed 放在我的rails_helper 文件中的require 'rspec/rails' 下方。如果您使用的是 database_cleaner gem - 需要进行一些调整以确保您在每次测试后不会丢失种子数据,您可以在 gem 的文档中找到它自己
require 'rails/test_help' 行之后将此添加到 test/test_helper.rb
应该是这样的
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:clone_structure is) 则不会执行 db:test:load
【讨论】:
--trace 运行 rake 帮助我了解了它是如何工作的。
task 'db:test:prepare' => 'db:seed'
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) 之前 Rake::Task["db:seed"].invoke
db:seed 运行时的环境是 development... 很奇怪。
在 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
【讨论】:
我相信上面的Steve's comment 应该是正确的答案。您可以使用Rails.application.load_seed 将种子数据加载到您的测试环境中。但是,加载这些数据的时间和频率取决于以下几点:
没有方便的方法在所有测试之前运行此文件一次(请参阅this Github issue)。您需要在每次测试之前加载一次数据,可能在测试文件的设置方法中:
# test/models/my_model_test.rb
class LevelTest < ActiveSupport::TestCase
def setup
Rails.application.load_seed
end
# tests here...
end
使用 RSpec 的 before(:all) 方法为该模型的所有测试加载种子数据:
describe MyModel do
before(:all) do
Rails.application.load_seed
end
describe "my model..." do
# your tests here
end
希望这会有所帮助。
【讨论】:
before(:suite)而不是before(:all)中调用它。发布了一个单独的答案以包含格式化的代码。
test_helper.rb 会导致种子文件多次运行,可能会由于重复键而导致错误。
我们正在调用 db:seed 作为 db:test:prepare 的一部分,其中:
Rake::Task["db:seed"].invoke
这样,种子数据在整个测试运行中加载一次,而不是每个测试类一次。
【讨论】:
将Rake::Task["db:seed"].invoke 添加到db:test:prepare rake 任务对我不起作用。如果我用rake db:test:prepare准备数据库,然后在测试环境中进入控制台,我所有的种子都在那里。但是,种子在我的测试之间没有持续存在。
不过,在我的设置方法中添加 load "#{Rails.root}/db/seeds.rb" 效果很好。
我想让这些种子自动加载并持续存在,但我还没有找到方法!
【讨论】:
对于使用种子库的用户,它会改变种子的加载方式,因此您可能不能/不想使用此处提供的load ... 解决方案。
只是将Rake::Task['db:seed'].invoke 放入 test_helper 会导致:
Don't know how to build task 'db:seed' (RuntimeError)
但是当我们在此之前添加 load_tasks 时,它起作用了:
MyApp::Application.load_tasks
Rake::Task['db:seed'].invoke
【讨论】:
基于 Matt 的回答,如果采用这种方式,我建议在 rspec_helper.rb 的 before(:suite) 块中调用 Rails.application.load_seed,而不是在任何文件中的 before(:all) 块中调用。这样一来,整个测试套件只调用一次种子代码,而不是每组测试一次。
rspec_helper.rb:
RSpec.configure do |config|
...
config.before(:suite) do
Rails.application.load_seed
end
...
end
【讨论】: