在集成测试中如何避免数据库回滚后挂起的请求失败?

时间:2019-04-24 17:53:19

标签: ruby-on-rails ruby capybara minitest

我们一直遇到一个间歇性问题,我想看看这里的人是否对如何解决这个问题有见识。 我们正在使用Minitest + Capybara和Chrome无头驱动程序进行集成测试。

当测试完成并且数据库被回滚时,就会发生此问题。仍然有一些未完成的请求在后台运行,如果尝试访问不可用的数据库信息,可能会崩溃(例如RecordNotFound)。

这种问题最常见是由于AJAX请求而引起的,为此,我们已经在使用 wait_for_ajax 帮助程序(我们自己开发)来等待浏览器完成请求。

<img> HTML标记发生了未解决的问题,因为即使测试已完成,浏览器仍可以尝试异步加载图像。

这是一个几乎总是会导致问题的代码示例:

test 'image popup should contain some class' do
  upload_some_images # Uploads images
  visit '/list_of_images' # Some page with list of images, you can click on the image and it opens it in a popup

  find('.image-popup-open-button').click # Open image in a popup window
  assert_selector '.some-class-must-be-present'
end

这是一个简单的测试,但是在我们的情况下,它总是会因ActiveRecord::RecordNotFound blob id=xxx错误而崩溃。

  • 打开弹出窗口时,会将<img src='/files/123' />添加到DOM。然后,浏览器对此进行查询,并将其重定向到ActiveRecord表示形式URL。
  • 集成测试非常简单,可以验证是否存在某些类,然后测试结束并且数据库已回滚。
  • /files/123的请求仍在运行,然后尝试加载不再存在的blob(数据库记录),并导致意外的测试失败。

有没有人遇到过这样的问题,如果有,您如何设法避免它?

我们正在使用Ruby 2.5.0,Rails 5.2.2,Capybara 3.0.3

谢谢

2 个答案:

答案 0 :(得分:1)

假设Capybara正在管理正在测试的应用程序的运行,Capybara.reset_sessions!将等待所有打开的请求完成。这需要在回滚数据库之前发生。如果使用Rails系统测试,只要您从已定义的任何teardown块中调用super,就将在teardown块中进行处理。如果不使用系统测试,而只是基于IntegerationTests进行测试,则需要定义一个调用teardown的{​​{1}}块,以使其在Rails回滚数据库之前等待所有请求完成。 / p>

答案 1 :(得分:0)

事实证明,我们是通过以下方式实现水豚的:

def after_teardown
  super
  Capybara.reset_sessions!
  Capybara.use_default_driver
end

但是Rails在super的{​​{1}}调用中回滚数据库。因此,在Capybara等待会话结束之前已回滚数据库。

after_teardown之后移动super可以达到目的(把它放在Capybara.reset_sessions!里面也很有意义,这很可能是我们要做的)。

感谢@ThomasWalpole向我指出正确的方向。