这是一个我几乎一无所知的领域,所以提前道歉。我有一套超过 800 个 rspec 测试。在运行整个集合或特定测试文件时突然莫名其妙地,在其中几个之后(比如 20 个左右,尽管它从来不是完全相同的数字),每个测试都开始失败并出现相同的错误:
Failure/Error: Unable to find matching line from backtrace
ActiveRecord::ConnectionTimeoutError:
could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)
在典型的运行中,我将在 20 次左右的请求测试后开始收到这些错误,其余 780 多次测试都失败,并出现上述完全相同的错误。我尝试回到之前完美测试过的 git commit 和分支。没有运气——仍然有 780 多次失败。还完全删除了重新创建的测试数据库。也没有运气。
我已经阅读了很多关于连接池等的线程,但恐怕我不知道如何诊断甚至发生了什么。以下是我现在所知道的事实:
- 使用 Postgresql
- 据我所知,开发环境运行良好
- 在一切正常和现在之间,我没有对我知道的环境进行任何更改/升级。甚至没有任何数据库迁移。仅更改模型、视图和控制器代码。正如我所提到的,回到以前的提交并不能解决任何问题。
config.use_transactional_fixtures = false
在 spec_helper.rb 中,因为我正在通过 Selenium 测试 ajax 功能。- 但是,无论 Selenium 是否用于特定的一组测试,测试都会失败。即使我只运行不使用 Selenium 的测试,在 20 次左右的测试后仍然会出现故障。
我使用的是具有以下配置的 Database Cleaner,而不是事务性装置:
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
有什么想法吗?更具体地说,我应该在哪里寻找问题所在的任何想法?我几乎没有处理这种类型的 ActiveRecord 问题的经验,我什至不知道从哪里开始。
更新虽然我仍然不知道为什么会发生这种情况,但我确实知道具体是什么代码导致了它。在最近的一次提交中,我在新线程中添加了发送通知电子邮件。这是代码:
def teacher_notification_email
Thread.new do
UserMailer.accepted_parent_invitation_email(@parent_profile).deliver
ActiveRecord::Base.connection.close
end
end
我在应用程序的许多其他地方都使用了这种精确的模式(使用不同的电子邮件),所有这些都经过测试。出于某种原因,这个特定的原因导致数据库超时错误。欢迎任何关于为什么会发生这种情况的想法。
更新 由于我不处于了解线程在这种情况下如何工作的阶段,因此我不知道问题的确切来源,除此之外:根据我所阅读的内容,很难以编程方式控制执行以这种方式创建的线程。但是,我找到了解决方案。而不是上面的块,我已将块更改为以下内容:
def teacher_notification_email
if Rails.env.test?
UserMailer.accepted_parent_invitation_email(@parent_profile).deliver
else
Thread.new do
UserMailer.accepted_parent_invitation_email(@parent_profile).deliver
ActiveRecord::Base.connection.close
end
end
end
所以我基本上运行不同的代码进行测试而不是开发 - 没有新的测试线程。我假设这是一个坏主意,但是直到我能理解真正的问题在哪里(无论出于何种原因,测试本身不会失败,或者仍然使用不强制测试失败的线程的代码),这个是我需要去的。
最终更新
我已经放弃了Thread.new
异步发送电子邮件的方法,而是实现了 Sidekiq。这是一个多一点的工作,但它运作良好并且测试良好......