我有一个升级到3.2.11版本的旧Rails应用程序,其中有许多使用capybara 1.0.1版本编写的请求规范,并使用selenium驱动程序运行。使用截断策略,在每次测试后使用database_cleaner清理数据库。
我想用poltergeist代替selenium,并将capybara从1.0.1升级到1.1.4,以便能够使用最新版本的poltergeist。仅更改capybara gem(及其依赖项)就会导致运行我的规范出现问题。
在每个spec之后的清理处理程序中,我总是从Postgresql数据库中得到死锁错误。
RSpec.configure do |config|
config.mock_with :rspec
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
我得到的错误是这样的:
An error occurred in an after hook
ActiveRecord::StatementInvalid: PG::Error: ERROR: deadlock detected
DETAIL: Process 41747 waits for AccessExclusiveLock on relation 17612 of database 16396; blocked by process 41752.
Process 41752 waits for RowExclusiveLock on relation 17529 of database 16396; blocked by process 41747.
HINT: See server log for query details.
: ALTER TABLE "aaa" ENABLE TRIGGER ALL;ALTER TABLE "bbbb" ENABLE TRIGGER ALL;ALTER TABLE "ccc" ENABLE TRIGGER ALL;
occurred at /xxx/.bundle/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:652:in `async_exec'
我使用FactoryGirl来创建测试数据,除此之外没有什么特别的。
我还没能弄清楚是什么保持死锁的另一端是由database_cleaner创建的。欢迎提出任何解决这个问题的建议。
有谁知道在capybara 1.0.1和1.1.4之间有什么变化,可能已经开始导致这些问题?
我在黄瓜中放置
来解决这个问题sleep 0.2
在步骤的末尾(或者在您的例子中是"spec"),它做一些AJAX的事情。我想发生的事情是,cucumber/rspec调用数据库清理器,而JS驱动程序仍在等待ajax响应。
修复不是使用sleep
,而是只使用Capybara API方法,因为它们等待预期的。
下面,行2失败(因为current_path
非等待),但行3工作(因为has_selector?
等待)。下面乔纳斯·尼克拉斯文章的链接很好地解释了这一点。
click_on 'signup_button' # Which does an AJAX redirect to /dashboard
assert_equal dashboard_path, current_path # This causes the deadlock error as Capybara doesn't wait.
assert page.has_selector?("#dashboard") # This works as it causes Capybara to wait for the new page.
http://www.elabs.se/blog/53-why-wait_until-was-removed-from-capybara 我们使用的解决方案是在页面中找到响应成功的ajax调用而应该更改的内容。比如:
click_on('Save')
expect(page).to have_content('Saved')