ruby-on-rails - Ruby on Rails 集成测试期间间歇性 ActiveRecord::RecordNotFound

标签 ruby-on-rails ruby-on-rails-3 activerecord integration-testing

我的集成测试间歇性失败,并且总是出现 ActiveRecord::RecordNotFound 错误。该错误发生在 Controller 内部,在给定固定装置 ID 的情况下,发生 find 调用。不过,它发生在多个 Controller 中。我在浏览网站时从未见过这种行为,但我想说测试失败的概率约为 30-50%。失败后再次运行测试似乎可以解决问题。

如果我将灯具手动加载到开发数据库中,似乎找不到的 ID 确实存在于表中。

我找不到太多关于遇到同样问题的人的信息...有什么想法吗?

更新:以下是 test_helper.rb 的内容

ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'capybara/rails'
class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
  #
  # Note: You'll currently still have to declare fixtures explicitly in integration tests
  # -- they do not yet inherit this setting
  fixtures :all
  # Add more helper methods to be used by all tests here...
end
# Transactional fixtures do not work with Selenium tests, because Capybara
# uses a separate server thread, which the transactions would be hidden
# from. We hence use DatabaseCleaner to truncate our test database.
DatabaseCleaner.strategy = :truncation
class ActionDispatch::IntegrationTest
  # Make the Capybara DSL available in all integration tests
  include Capybara::DSL
  # Make the Capybara Email DSL available in all integration tests
  include Capybara::Email::DSL
  # Stop ActiveRecord from wrapping tests in transactions
  self.use_transactional_fixtures = false
  # Switch to selenium as the default driver for JS support
  Capybara.default_driver = :selenium
  # Only click on visible links!
  Capybara.ignore_hidden_elements = true
  teardown do
    DatabaseCleaner.clean       # Truncate the database
    Capybara.reset_sessions!    # Forget the (simulated) browser state
    Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
  end
end

更新以下是连续运行相同测试 5 次的结果。我运行了测试,等到它们完成,然后立即使用命令 rails test:integration 再次运行它们。注意:在整个测试中保持一致的 E 和 F 实际上是测试错误——我正在努力修复这些错误。例如,第二次测试运行是“正确的”,但第一次测试显示了虚假错误。

..E......E..........F.
.........E..........F.
..E......E..........F.
..E......E..........F.
..E....E.E..........F.

错误确实发生在两个单独的表中——它们并不是试图查找相同的记录。但它似乎只是存在此问题的测试的子集......

更新以下是测试结果中的实际错误:

  1) Error:
test_browsing_user_snops(BrowseStoriesTest):
ActiveRecord::RecordNotFound: Couldn't find User with id=980190962
    /home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/relation/finder_methods.rb:341:in `find_one'
    /home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/relation/finder_methods.rb:312:in `find_with_ids'
    /home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/relation/finder_methods.rb:107:in `find'
    /home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/querying.rb:5:in `find'
    /home/myuser/Projects/myproject/app/controllers/users_controller.rb:18:in `show'
    ...

请注意,当 Controller 尝试查找记录时会出现错误。相关行实际上是@user = User.find(params[:id])。其他模型也会发生这种情况,不仅仅是用户 Controller ,也不仅仅是用户模型。

最佳答案

我担心数据截断期间可能会出现延迟,并且 Capybara 驱动 Web 浏览器的速度有时可能会导致标识列值以意外值开始(即记录 #1 为 7) - 当您期望 1 时,因为身份生成器尚未重置)。我没有证据表明情况确实如此,但这是我的最佳猜测。

获取look at item #3 at this URL 。这是一个非常简单的黑客攻击,将 use_transactional_fixtures 设置为 true 并通过将该代码粘贴到 test_helper.rb 中来对 ActiveRecord 进行 Monkeypatch。这有助于消除任何可能成为潜在问题的间歇性磁盘 IO 问题。

您可以尝试的另一件事是通过在 database.yml 文件中将数据库的文件名设置为 :memory: 来限制您的 SQLite 测试数据库。这应该完成与上面相同的事情 - 消除可能导致这些间歇性问题的虚假磁盘 IO。

关于ruby-on-rails - Ruby on Rails 集成测试期间间歇性 ActiveRecord::RecordNotFound,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13617152/

相关文章:

ruby-on-rails - 在 Ruby on Rails 中创建动态页面

ruby-on-rails - Rails-更新nested_attributes不适用于一对多关系

ruby-on-rails - rails : how to add comment on fields?

ruby-on-rails-3 - 关于 Google Analytics 跟踪(使用 Rails)的问题

jquery - Rails 和数据禁用与 Safari 不兼容

ruby-on-rails - 如何告诉 Rails 在部署时使用生产数据库(而不是开发数据库)?

ruby-on-rails - ActiveRecord 未检索所有模型

php - 如何在 yii2 'where' 中编写子查询?

ruby-on-rails - 如何在生产环境中添加时间格式?

ruby-on-rails - 在 Cassandra 的 Rails 中定义表复合主键