防止 Rails 测试删除种子数据

发布于 2024-08-14 13:21:34 字数 774 浏览 10 评论 0原文

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

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

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

结果是此断言在 seeds.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 不再处理种子数据?我是否需要复制灯具中的所有数据以确保重新加载?如果没有重大政治事件,我预计国家数据将相对稳定。

蒂亚

I am using seeds.rb to populate some State model reference data:

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

Although I am not using state fixtures (since it's seed data to begin with, I think it wouldn't be DRY to have to duplicate this purely for tests), the Rails testing framework seems to delete all the State seed data during testing. (I am dropping, recreating, migrating and reseeding the test db, and confirmed the data is there prior to a unit test running.)

The result is this assertion succeeding in seeds.rb but failing in a one-line test:

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

I have tried both explicitly listing non-State models in the base test class fixtures statement, as well as flipping the transactional fixtures flag (as expected, this only affects records created during the test). Naturally the test under consideration is not itself deleting these records.

The State records are always deleted. Is there a way to tell Rails to just get its hands off the seed data? Do I need to duplicate all the data in fixtures to make sure it gets re-loaded? Short of a major political event, I would expect the state data to be relatively stable.

tia

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不必在意 2024-08-21 13:21:34

测试从数据库中删除所有数据,然后加载您的灯具(如果有)。

您需要让测试助手在测试运行之前加载种子文件。有几种方法可以做到这一点,请查看我的类似问题: 如何自动将 db:seed 数据加载到测试数据库中?

最简单的方法可能就是在

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

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

Tests delete all the data from the database and then load your fixtures (if you have any).

You need to get your test helper to load the seed file before the tests run. There are a couple ways to do that, check out my similar question: How to load db:seed data into test database automatically?

The easiest way is probably just to add

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

to the top of your test_helper.rb file (assuming you use the built-in testing framework).

把时间冻结 2024-08-21 13:21:34

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

然而,用种子数据填充数据库非常简单。

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

class ActionSupport::TestCase < ...

  setup :load_seeds

  protected 

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

end

The "seed" feature is not integrated into the test architecture. Tests are built around fixtures and each time you run the test suite, Rails loads the data from the fixtures and replaces the existing content.

However, having the database populated with your seed data is really straightforward.

In your test_helper.rb file add a new setup method in the base ActionSupport::TestCase class.

class ActionSupport::TestCase < ...

  setup :load_seeds

  protected 

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

end
獨角戲 2024-08-21 13:21:34

我同意 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 提供许多现有的赛程。

I agree with weppos as to the best way to do this, however for the sake of completeness and for the sake of people who may already have fixture files you can take the other approach and seed your database from the existing fixtures.

This is accomplished by doing something like the following in the db/seeds.rb file

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

You could alternatively read the fixures directory and create an array of file names to process, I chose the above process as I wished to be able to specify which of my many existing fixtures I wished to seed the DB with.

屋顶上的小猫咪 2024-08-21 13:21:34

我首先质疑是否需要编写这样的测试。您是在测试种子数据提取任务是否正常工作,还是想测试 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或其他与测试相关的任务时。

I question the need to write a test like that in the first place. Are you testing that the seed data rake task works properly or do you want to test the behavior of your implementation of the State class? I'm assuming the latter, so I would write tests that focus on the behavior and use Factory Girl (or similar) since you mention that you're not using fixtures. Make sure to remove the fixtures :all line from test/test_helper.rb.

To inject a task into the normal flow of running tests, this is an approach that has always worked for me:

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

Just put that in a file called lib/tasks/testing.rake and it will get picked up when you next run rake test or other test-related task.

风铃鹿 2024-08-21 13:21:34

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

我的问题涉及类文件中对常量和named_scopes进行数据库查找的位置。我找不到任何方法可以在正确的时间加载种子数据。

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

RAILS_ENV=测试耙数据库:种子
ruby -Itest 测试/单位/*.rb

I had the same problem, but the standard answer didn't work for me.

My problem involved places in the class files which did a database lookup for constants and named_scopes. I could not find any way to have the seed data loaded at the right time.

I did find a way to by-pass the delete, which was happening even though I had deleted my fixture file for the missing table.

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

云裳 2024-08-21 13:21:34

默认情况下,您无法同时应用seedfixtures 来设置同一 的数据。

例如。如果您设置名为products.yml的装置,它将在创建装置期间“从产品中删除数据”。

您可以:

  1. 种子的舞台移至灯具后面(手动加载种子);
  2. 仅使用其中一种或替代方法来管理测试数据;
  3. 不要使用这两种方法来设置同一个表的数据;
  4. 在Rails4.2中,你可以破解这个
    像这样:

>

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

这在某些遗留情况下会有所帮助,但弄乱种子固定装置可能会带来新问题。

You can't apply both seed and fixtures to setup a same table's data by default.

eg. If you set up a fixtures named products.yml, it will "delete data from products" during creating fixtures.

You can:

  1. Move the seed's stage behind the fixturess(load seed manually);
  2. Use just one of them, or an alternative approach to manage test data;
  3. Don't use both approach to setup a same table's data;
  4. In Rails4.2, you can hack this line in your test_helper.rb
    like this:

>

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

This would help in some legacy case, but messing seeds and fixtures up may brings new problems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文