#ruby-on-rails #ruby #capybara #minitest
#ruby-on-rails #ruby #capybara #minitest
Вопрос:
У нас периодически возникает проблема, и я хотел бы узнать, есть ли у кого-нибудь здесь представление о том, как мы можем ее решить. Мы проводим наши интеграционные тесты с Minitest Capybara и драйвером Chrome headless.
Проблема возникает, когда тест завершен, и база данных получает ОТКАТ. В фоновом режиме все еще могут выполняться некоторые незавершенные запросы, и могут возникать сбои (например, 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
ошибкой.
- При открытии всплывающего окна в DOM добавляется
<img src='/files/123' />
. Затем браузер запрашивает это и перенаправляется на URL-адрес представления ActiveRecord. - Интеграционный тест довольно прост и проверяет, присутствует ли какой-либо класс, после чего тест завершается и выполняется ОТКАТ базы данных.
- Запрос на
/files/123
все еще выполняется, который затем пытается загрузить большой двоичный объект (запись базы данных), который больше не существует, и приводит к неожиданному сбою теста.
У кого-нибудь когда-либо была такая проблема, если да, то как вам удалось ее избежать?
Мы используем Ruby 2.5.0, Rails 5.2.2, Capybara 3.0.3
Спасибо
Комментарии:
1. Какую версию Rails вы используете? Используете ли вы средство очистки базы данных? Какая версия Capybara? Вы переопределили поведение сброса сеанса Capybara по умолчанию? Вы разрешаете Capybara управлять запуском тестируемого приложения или вы отключили это? Текущая настройка Capybaras по умолчанию должна ожидать завершения всех запросов при сбросе сеанса, если только вы не отключили это, пытаясь выполнить пользовательские действия.
2. Хорошо — Вы используете Rails 5.2.2, поэтому вам не следует использовать database_cleaner, поскольку Rails обрабатывает это из Rails 5.1 — Вы пишете системные тесты Rails? Если да, то у вас случайно не было записанных
teardown
блоков, которые вы забыли вызватьsuper
? Если это так, это предотвратит вызов Capybarasreset_sessions!
, где Capybara ожидает завершения всех текущих запросов, прежде чем двигаться дальше. Если вы не используете системные тесты, есть ли у вас собственныйteardown
блок, который вызываетCapybara.reset_sessions!
в конце теста? Кроме того, Capybara 3.0.3 в настоящее время устарела3. Привет @ ThomasWalpole, я обновил вопрос версиями gem, спасибо, что напомнили мне поставить их. Мы не используем какой-либо драгоценный камень для очистки базы данных, мы используем rails-приспособления. Для поведения сеанса мы внедрили что-то вроде этой документации , хотя я заметил, что мы переопределили
def after_teardown
и неdef teardown
, не уверен, что это сильно изменится. Ваш вопрос «разрешить Capybara управлять запущенным тестируемым приложением», я не уверен, что вы имеете в виду, извините.4.
after_teardown
vsteardown
будет иметь огромное значение, если БД откатывается во времяteardown
—Capybara.reset_sessions!
необходимо вызвать до отката БД (я не помню, на каком этапе Rails откатывается в интеграционных тестах — но системные тесты специально вызывают reset_sessions из teardown, а не after_teardown, поэтому я предполагаю, что это должно быть вteardown
— попробуйте и посмотрите) Все это предполагает, что вы разрешаете Capybara запускать приложение (вы не установили Capybara.run_server = false, а затем установилиapp_host
для другого экземпляра приложения, для которого вы управляете запуском)5. Что ж! @ThomasWalpole Ты мой мужчина! Это действительно был
teardown
vsafter_teardown
. Rails, скорее всего, выполняет откат в,after_teardown
потому что после перемещенияsuper
вызова послеCapybara.reset_sessions!
это сработало. Спасибо, что указали мне правильные направления, мои знания о Capybara все еще ограничены, поэтому я не смог точно определить, когда / где что-то происходит.
Ответ №1:
Предполагая, что Capybara управляет запуском тестируемого приложения, Capybara.reset_sessions!
будет ждать завершения всех открытых запросов. Это должно произойти до того, как база данных будет откатана. При использовании системных тестов Rails это будет обрабатываться в teardown
блоке до тех пор, пока вы вызываете super
из любых teardown
определенных вами блоков. Если вы не используете системные тесты и просто основываете свои тесты на IntegerationTests, вам нужно определить teardown
блок, который вызывает Capybara.reset_sessions!
, чтобы он ожидал завершения всех запросов, прежде чем Rails откатит базу данных.
Ответ №2:
Оказалось, что мы реализовали Capybara таким образом:
def after_teardown
super
Capybara.reset_sessions!
Capybara.use_default_driver
end
но Rails выполняет откат базы данных при super
вызове after_teardown
. Таким образом, база данных была откатана до того, как Capybara ожидает завершения сеанса.
Перемещение super
after Capybara.reset_sessions!
сделало свое дело (также имеет смысл вместо этого поместить его внутрь def teardown
, что, скорее всего, мы и сделаем).
Спасибо @ThomasWalpole за то, что указал мне правильное направление.