【问题标题】:Prevent Rails test from deleting seed data防止 Rails 测试删除种子数据
【发布时间】:2010-12-26 07:23:16
【问题描述】:

我正在使用 seed.rb 来填充一些状态模型参考数据:

State.create :name => 'Alabama', :abbreviation => 'AL'
State.create :name => 'Alaska', :abbreviation => 'AK'
# ...

虽然我没有使用状态装置(因为它最初是种子数据,我认为纯粹为了测试而必须复制它并不是 DRY),Rails 测试框架似乎删除了所有状态种子数据测试。 (我正在删除、重新创建、迁移和重新播种测试数据库,并在单元测试运行之前确认数据存在。)

结果是这个断言在 seed.rb 中成功,但在单行测试中失败:

assert_equal 51, State.all.size

1) Failure:
test_state_seeds_are_present(StateTest) [/test/unit/state_test.rb:24]:
<51> expected but was
<0>.
1 tests, 1 assertions, 1 failures, 0 errors

我已经尝试在基类测试装置语句中明确列出非状态模型,以及翻转事务装置标志(正如预期的那样,这只会影响测试期间创建的记录)。当然,正在考虑的测试本身不会删除这些记录。

状态记录总是被删除。有没有办法让 Rails 从种子数据中解放出来?我是否需要复制夹具中的所有数据以确保重新加载?在没有重大政治事件的情况下,我预计州数据会相对稳定。

tia

【问题讨论】:

  • 谢谢大家,我将尝试 Luke 的(一次性)和 weppos 的(设置时)建议在测试中显式加载种子数据,看看哪一个最适合我的目的。我会认为测试总是首先核对数据库数据。

标签: ruby-on-rails ruby testing fixtures seed


【解决方案1】:

测试会从数据库中删除所有数据,然后加载您的设备(如果有的话)。

您需要让测试助手在测试运行之前加载种子文件。有几种方法可以做到这一点,看看我的类似问题:How to load db:seed data into test database automatically?

最简单的方法可能就是添加

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

到您的 test_helper.rb 文件的顶部(假设您使用内置测试框架)。

【讨论】:

  • 这对我不起作用,如果我将该行添加到我的夹具中它可以正常工作,但如果我把它放在 test_helper.rb 中,种子数据似乎在我的测试到达之前就消失了.
  • 您是否有一个固定 yml 文件,用于您尝试填充到种子文件中的类?因为当夹具运行时,这将清除所有数据。删除种子的夹具文件;或者如果您不能这样做,请使用 Simone 的示例,其中在每次测试之前加载夹具数据。
  • 啊,我已经注释掉了我的 .yml 文件,但这似乎还不够,它的存在会导致种子数据被覆盖。删除了,一切正常,谢谢Luke的帮助
  • 是的,这有点违反直觉,但如果 yml 文件在那里并且为空,它仍然会删除该表的内容。
【解决方案2】:

“种子”功能未集成到测试架构中。测试是围绕夹具构建的,每次运行测试套件时,Rails 都会从夹具加载数据并替换现有内容。

但是,用种子数据填充数据库非常简单。

在您的 test_helper.rb 文件中,在 ActionSupport::TestCase 基类中添加一个新的设置方法。

class ActionSupport::TestCase < ...

  setup :load_seeds

  protected 

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

end

【讨论】:

  • 这将在每个测试用例之前重新加载您的种子数据,这给出了您可能不需要做的事务性固定装置。只要种子数据应该保持不变(它应该),你应该只需要加载一次。
  • 这就是我认为的卢克,但无论如何它似乎都被删除了,所以听起来我将不得不实施某种解决方法以确保它存在于数据库中进行测试.
  • 你的 fixtures 目录中有 states.yml 文件吗?即使它是空的,它也会导致您的状态数据被删除。我总是确保删除我的种子数据表的固定装置(实际上我根本不再使用固定装置,但那是另一回事了)。
  • 是的,我确实/确实有一个 states.yml(空)。删除它(好吧,重命名它)是我尝试过的事情之一,但它似乎没有帮助。但我会再试一次,因为我仍然有兴趣看看我是否可以阻止它甚至尝试删除数据。
【解决方案3】:

我同意 weppos 的最佳做法,但为了完整性和可能已经拥有夹具文件的人,您可以采用其他方法并从现有夹具中为您的数据库播种。

这是通过在 db/seeds.rb 文件中执行以下操作来完成的

RAILS_FIXTURES = "#{Rails.root}/spec/fixtures"

models_loaded_from_fixtures = %w[Modela Modelb Modelc ....]

models_loaded_from_fixtures.each do |model|
  Fixtures.create_fixtures(RAILS_FIXTURES, "#{model.tableize}")
  puts "Loaded #{model.constantize.all.size} #{model.pluralize}"
end

您也可以读取 fixures 目录并创建要处理的文件名数组,我选择了上述过程,因为我希望能够指定我希望使用我的许多现有固定装置中的哪一个作为 DB 的种子。

【讨论】:

    【解决方案4】:

    我质疑是否需要首先编写这样的测试。您是在测试种子数据 rake 任务是否正常工作,还是要测试您的 State 类实现的行为?我假设是后者,所以我会编写专注于行为的测试并使用 Factory Girl(或类似的),因为您提到您没有使用固定装置。确保从test/test_helper.rb 中删除fixtures :all 行。

    要将任务注入到运行测试的正常流程中,这是一种一直对我有用的方法:

    namespace :test do
      task :force_environment do
        ENV['RAILS_ENV'] = 'test'
        RAILS_ENV.replace('test')
      end
    end
    
    %w(test:units test:functionals test:integration).map do |task_name|
      task = Rake::Task[task_name]
      task.clear_prerequisites
    
      task.enhance %w(db:test:prepare test:force_environment db:seed)
    end
    

    只需将其放入名为 lib/tasks/testing.rake 的文件中,当您下次运行 rake test 或其他与测试相关的任务时,它就会被拾取。

    【讨论】:

    • 嗨帕特里克。我实际上不需要测试状态模型本身,这只是一个证明种子数据不存在的例子。状态模型(参考数据)用于验证地址,地址验证测试失败,因为状态数据不在数据库中。
    • 这更有意义。 Rake 任务应该对您有用,但听起来您的工作正常。
    【解决方案5】:

    我遇到了同样的问题,但标准答案对我不起作用。

    我的问题涉及类文件中的位置,这些文件对常量和命名范围进行了数据库查找。我找不到任何方法在正确的时间加载种子数据。

    我确实找到了绕过删除的方法,即使我已经删除了丢失表的固定文件,也会发生这种情况。

    RAILS_ENV=测试 rake db:seed ruby -Itest test/units/*.rb

    【讨论】:

      【解决方案6】:

      你不能同时应用seedfixtures来默认设置相同的table的数据。

      例如。如果你设置了一个名为products.yml的fixture,它会在创建fixtures时“从产品中删除数据”。

      你可以:

      1. seed 的舞台移到fixturess 后面(手动加载种子);
      2. 仅使用其中一种方法,或使用其他方法来管理测试数据;
      3. 不要同时使用这两种方法来设置同一个表的数据;
      4. 在 Rails4.2 中,您可以在 test_helper.rb 中破解此 line 像这样:

      >

      require 'rails/test_help'
      
      class ActiveRecord::FixtureSet
        def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
          ...
          # table_rows.each_key do |table|
          #   conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
          # end
          ...
        end
      

      这在某些遗留情况下会有所帮助,但将 seedsfixtures 搞乱可能会带来新问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-14
        • 1970-01-01
        • 2018-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-07
        相关资源
        最近更新 更多