将capybara从1.0.1升级到1.1.4会使database_cleaner破坏我的规格

时间:2013-01-10 19:43:20

标签: ruby-on-rails selenium rspec capybara database-cleaner

我有一个旧的Rails应用程序升级到版本3.2.11,它有很多使用capybara版本1.0.1编写并使用selenium驱动程序运行的请求规范。使用database_cleaner使用截断策略在每次测试后清理数据库。

我想使用poltergeist而不是selenium并将capybara从1.0.1升级到1.1.4以便能够使用最新版本的poltergeist。只更改capybara gem(及其依赖项)引入了运行我的规范的问题。

在每个规范之后,我一直在清理处理程序中从Postgresql数据库中获得死锁错误。我的spec_helper很基本,看起来像这样:

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创建测试数据,但没有其他特殊的IMO。

我无法弄清楚由database_cleaner创建的死锁的另一端是什么。任何想出来的想法都是最受欢迎的。

任何人都知道capybara 1.0.1和1.1.4之间的任何变化已经发生变化并且可能已经开始引起这些问题了吗?

3 个答案:

答案 0 :(得分:5)

我通过放置黄瓜解决了这个问题

sleep 0.2

在执行某些AJAX操作的步骤结束时(或者在您的情况下为“spec”)。我想,当JS驱动程序仍在等待ajax响应时,yellow / rspec会调用数据库清理器。

答案 1 :(得分:5)

修复不是使用sleep,而是仅使用Capybara API方法,因为它们会等待预期的结果。

下面,第2行失败(因为current_path没有等待,但第3行正常工作(如has_selector?所等)。下面Jonas Nicklas的文章链接说明了这一点。

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

答案 2 :(得分:1)

我们使用的解决方案是在页面中找到应该响应成功的ajax调用而改变的内容。如下所示:

click_on('Save')
expect(page).to have_content('Saved')