如何避免在集成测试中数据库回滚后挂起的请求失败?
How to avoid pending requests to fail after database rollback in integration tests?
我们一直遇到间歇性问题,我想看看这里是否有人知道我们如何解决它。
我们正在使用 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
错误。
- 打开弹出窗口 window 时,会在 DOM 中添加一个
<img src='/files/123' />
。然后浏览器查询并重定向到 ActiveRecord 表示 URL.
- 集成测试非常简单,验证是否存在某些 class,然后测试完成,数据库回滚。
/files/123
的请求仍然是运行,然后尝试加载一个不再存在的blob(数据库记录),导致意外的测试失败。
有没有人遇到过这样的问题,如果遇到过,你是怎么避免的?
我们正在使用 Ruby 2.5.0,Rails 5.2.2,水豚 3.0.3
谢谢
原来我们是这样实现 Capybara 的:
def after_teardown
super
Capybara.reset_sessions!
Capybara.use_default_driver
end
但是 Rails 在 after_teardown
的 super
调用中回滚了数据库。因此在 Capybara 等待会话完成之前数据库已回滚。
在 Capybara.reset_sessions!
之后移动 super
达到了目的(将它放在 def teardown
中也是有意义的,这很可能是我们要做的)。
感谢@ThomasWalpole 为我指明了正确的方向。
假设 Capybara 正在管理正在测试的应用程序的 运行,Capybara.reset_sessions!
将等待所有打开的请求完成。这需要在数据库回滚之前发生。如果使用 Rails 系统测试,这将在 teardown
块中处理,只要您从您定义的任何 teardown
块中调用 super
。如果不使用系统测试并且只是将测试基于 IntegerationTests,则需要定义一个调用 Capybara.reset_sessions!
的 teardown
块,以便在 Rails 回滚之前等待所有请求完成数据库。
我们一直遇到间歇性问题,我想看看这里是否有人知道我们如何解决它。 我们正在使用 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
错误。
- 打开弹出窗口 window 时,会在 DOM 中添加一个
<img src='/files/123' />
。然后浏览器查询并重定向到 ActiveRecord 表示 URL. - 集成测试非常简单,验证是否存在某些 class,然后测试完成,数据库回滚。
/files/123
的请求仍然是运行,然后尝试加载一个不再存在的blob(数据库记录),导致意外的测试失败。
有没有人遇到过这样的问题,如果遇到过,你是怎么避免的?
我们正在使用 Ruby 2.5.0,Rails 5.2.2,水豚 3.0.3
谢谢
原来我们是这样实现 Capybara 的:
def after_teardown
super
Capybara.reset_sessions!
Capybara.use_default_driver
end
但是 Rails 在 after_teardown
的 super
调用中回滚了数据库。因此在 Capybara 等待会话完成之前数据库已回滚。
在 Capybara.reset_sessions!
之后移动 super
达到了目的(将它放在 def teardown
中也是有意义的,这很可能是我们要做的)。
感谢@ThomasWalpole 为我指明了正确的方向。
假设 Capybara 正在管理正在测试的应用程序的 运行,Capybara.reset_sessions!
将等待所有打开的请求完成。这需要在数据库回滚之前发生。如果使用 Rails 系统测试,这将在 teardown
块中处理,只要您从您定义的任何 teardown
块中调用 super
。如果不使用系统测试并且只是将测试基于 IntegerationTests,则需要定义一个调用 Capybara.reset_sessions!
的 teardown
块,以便在 Rails 回滚之前等待所有请求完成数据库。