使用rake从db/seeds.rb自动加载种子数据

Zag*_*g.. 20 testing rake rspec ruby-on-rails-3

我正在使用rails-rspecgem,我有几个规格(模型,控制器等).当我跑:

bundle exec rake
Run Code Online (Sandbox Code Playgroud)

一切都经过测试 但是,我想通过在创建数据库之后(在测试环境中)播种一些数据(来自db/seeds.rb)来改进我的规范.

我的spec/spec_helper.rb文件如下所示:

ENV["RAILS_ENV"] ||= 'test'

require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rspec'
require 'ruby-debug'

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  config.mock_with :rspec

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = false

  config.include SpecHelper

  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.start
    stub_xmpp_rest_client!  
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.include Devise::TestHelpers, :type => :controller
  config.include Delorean
  config.after(:each) { back_to_the_present }
  config.include Factory::Syntax::Methods
  config.extend ControllerMacros, :type => :controller
end
Run Code Online (Sandbox Code Playgroud)

有什么办法可以做到最好?谢谢.

Mar*_*ser 44

馊主意!从来没有,为您的测试数据库提供种子.使用工厂在每个测试中创建该测试通过所需的记录.播种测试数据库将使您的测试不太可靠,因为您将做出许多未在测试中明确说明的假设.

  • 我们中的一些人正在构建与......现实相结合的系统,其中耦合需要相当强大.大多数情况下,我不希望或在我的测试中使用种子数据,但有时你会这样做,在这种情况下,找到一种优雅的方式很好.例如,我的应用程序有一些常量值存储在DB而不是Ruby CONSTANTS中,它们需要参与测试. (81认同)
  • 我同意你的意见,@ marnen-laibow-koser.但是,如您所知,种子目的是减少对应用程序至关重要的数据.这就是为什么我认为它对于测试场景很有用. (2认同)
  • @ DavidN.Welton你错了.种子数据不是应用程序的一部分,比任何其他数据都要多.生产种子数据应该存在于*no*测试中,因为包含它将远远超出测试运行所需的最小设置.*应该*存在的是最小的制作数据(通常不超过大约10个记录) - 足以让测试通过.如果您为数据库播种测试,那么最终会出现脆弱,不清晰,紧密耦合的测试 - 测试所不应该进行测试.这不是一种"态度"; 这是一个可证明的事实. (2认同)
  • @TarynEast然后我认为你做错了,可能是因为你并不真正理解你的方法的缺点.使用数据库/种子文件,您可以将种子扫到地毯下,从而隐藏您的假设.在测试中,这是*糟糕*.每个测试都应该使其假设明确 - 并且这样做的方法是在每个测试中从零开始,并且仅为该测试创建***所需的记录*.工厂定义通常不会比种子文件复杂,并且可能不那么复杂.(另外,你自己指出你正在滥用数据库/种子.) (2认同)

Tar*_*ast 29

根据种子文件的配置方式,您可能只能从块before(:each)before(:all)块加载/运行它:

load Rails.root + "db/seeds.rb" 
Run Code Online (Sandbox Code Playgroud)


And*_*Vit 12

我将我的rake spec任务设置为自动加载db/seeds.rb,所以我依赖它来为第一次运行设置数据库.将其添加到您的Rakefile:

task :spec     => "db:seed"
task :cucumber => "db:seed"
Run Code Online (Sandbox Code Playgroud)

然后,在后续运行中,我只是rspec spec直接调用跳过种子步骤,避免不必要的重新加载.我配置数据库清理程序忽略种子表,如下所示:

RSpec.configure do |config|

  config.add_setting(:seed_tables)
  config.seed_tables = %w(countries roles product_types)

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation, except: config.seed_tables)
  end

  config.around(:each) do |example|
    if example.metadata[:no_transactions]
      DatabaseCleaner.strategy = :truncation, {except: config.seed_tables}
    else
      DatabaseCleaner.strategy = :transaction
    end
    DatabaseCleaner.start
    example.run
    DatabaseCleaner.clean
  end
end
Run Code Online (Sandbox Code Playgroud)

对于需要提交数据的方案,我可以添加:

describe "commit for real", use_transactions: false do
  # ...
end
Run Code Online (Sandbox Code Playgroud)

除了种子表之外,这将截断示例运行后的所有内容.假设你从不在种子表上写任何东西!这通常是安全的假设,因为种子数据通常是静态的.

对于所有其他正常情况,我依赖事务来回滚任何插入的记录.数据库返回到原始状态,种子表中的数据保持不变.如果需要,可以在此处写入种子表.

要重建种子表,只需rake spec再次运行即可.


Ahm*_*ain 7

要在rspec中加载种子,您​​需要在spec_helper中的confg.before(:suite)中进行数据库清理后添加它

config.before(:suite) do
  DatabaseCleaner.clean_with(:truncation)
  load "#{Rails.root}/db/seeds.rb" 
end
Run Code Online (Sandbox Code Playgroud)


And*_*ban 7

Rails 4.2.0RSpec 3.x中,这就是我的rails_helper.rb的外观.

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = false

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.before(:all) do
    Rails.application.load_seed # loading seeds
  end
end
Run Code Online (Sandbox Code Playgroud)