Много тестов - это хорошо, особенно если они еще и по делу.
Но много тестов - это время, которое они занимают в процессе выполнения. И если его можно уменьшить - почему бы это не сделать.
Вдохновившись описанными получаемыми результатами:
Отметим что Ferrum работает в 5-10 раз быстрее чем другие фреймворки.
Тестирование пользовательских сценариев с помощью FerrumOur tests are much faster
Migrating Selenium system tests to CupriteFerrum is faster than Selenium
- Open-sourcing Ferrum: a fearless Ruby Chrome driver
, пробуем использовать ferrum вместо "медленных" selenium-webdrivers.
Чтобы получить относительно сопоставимые результаты, сделаем отдельный MR и сравним, что получится ДО и ПОСЛЕ.
Количество и качество тестов - одинаковое в данном случае.
Настройки
Как и описано, например вот здесь - Proper browser testing in Ruby on Rails (evil martians), настройки не представляют большой сложности.
Gemfile
...
+ gem 'cuprite'
- gem 'webdrivers'
...
Конфигурация драйвера
Capybara.server = :puma, { Silent: true }
Capybara.register_driver :cuprite do |app|
# FIXME: Two different keys for headless mode exist - one for Capybara (Cuprit) and one for Chromium - headless mode
# [Chrome's headless mode](https://developer.chrome.com/articles/new-headless/#new-headless-in-selenium-webdriver)
# It's impossible to set two keys with the same values - does not work
if ENV['HEADLESS'].in?(%w[n 0 no false])
browser_options = { 'no-sandbox': nil }
headless = false
else
browser_options = { 'no-sandbox': nil, headless: 'new' }
headless = 'new'
end
options = {
browser_options:,
window_size: [1600, 1200],
inspector: true,
headless:
# js_errors: true
# slowmo: 2,
# process_timeout: 15
}
Capybara::Cuprite::Driver.new(app, options)
end
Capybara.save_path = DownloadHelpers::DOWNLOAD_PATH || './tmp/capybara'
# disable CSS transition and jQuery animation
Capybara.disable_animation = true
# Usually, especially when using Selenium, developers tend to increase the max wait time.
# With Cuprite, there is no need for that.
# We use a Capybara default value here explicitly.
# Capybara.default_max_wait_time = 2
# Normalize whitespaces when using `has_text?` and similar matchers,
# i.e., ignore newlines, trailing spaces, etc.
# That makes tests less dependent on slightly UI changes.
Capybara.default_normalize_ws = true
Capybara.javascript_driver = :cuprite
Запуск. Ошибки
Как и описано в упомянутых источниках и в ссылках внизу, часть тестов завершилась с ошибками. Примерное количество - 15-20% от общего числа.
Ошибки поделились на несколько категорий.
Самая распространенная
перестают работать одни из самых используемых методов - click_link (и его разновидности, например find('#id_blabla').click).
Причина оказалась простая и отчасти уважительная, драйвер "пытается" детально разобраться в структуре линка и, обнаруживая в нем что-то еще, выдает ошибку.
Это "что-то еще" оказалось используемыми css наподобие ::before, используемыми bootstrap и bulma для, например, смены background строки таблицы при наведении.
Везде, где применяются еще какие то дополнительные анимационные css, метод click_link не будет работать.
Пользуясь подсказкой ferrum (или cuprite), меняем click на trigger('click'), игнорируя предупреждение о том, что возможно нажимаем не совсем в той области, где планировали.
Обнаруживается вторая ошибка - метод trigger('click') на "нормальных" без css линках не работает.
Делаем два разных шага в cucumber для устранения данных ошибок, разбираемся, где линки с css, а где нет - и в результате большая часть (примерно 95%) тестов начинает работать с новым драйвером.
Ошибка два
Часть тестов, использующих прямой вызов JS для того, чтобы установить или получить значение из применяемых компонент, не работает.
Устанавливаемые значения - все срабатывает, а вот возвращается всегда nil.
В описании Ferrum JavaScript находим, что для выполнения JS и выполнения с возвратом значения используются разные методы (evaluate/execute).
Возможно при реализации Cuprite этот нюанс не был учтен, меняем метод там, где необходимы значения и тесты начинают работать.
Ошибка три
Вызвана тем, что headless и headful режим работает различно. Проявляется это просто - в режиме headful тест выполняется, в режиме headless - падает с ошибкой, связанной с тем, что не отрабатывает стандартная функция onchange: 'this.form.submit()'.
Руководствуясь документом от Google Chrome’s Headless mode меняем headless mode на новую.
Здесь возникает еще один не очень понятный момент, связанный с тем, что mode определяется в ДВУХ местах. В настройках параметров драйвера и в настройках параметров браузера драйвера. В итоге пока оставляем так, как приведено выше в конфигурации.
И после этого все тесты начинают работать.
Результаты
Это не benchmark, это просто вывод времени выполнения каждого теста для одной и той же группы тестов, на одной и той же локальной машине.
Исходные данные:
Количественные показатели тестов
Cucumber 70 scenarios (550 steps)
RSpec 346 examples
Характеристики компьютера
Linux version 5.15.0-76-generic (buildd@lcy02-amd64-028)
Intel(R) Xeon(R) CPU E5-2697A v4 @ 2.60GHz
16373244 K total memory
Измерения скорости выполнения тестов
Измерения проводились исключительно с целью примерного сравнения без применения каких либо специализированных инструментов.
Для "усреднения" использовалась command-line benchmarking tool
cuprite
RSpec
(Migrate_to_ferrum) hyperfine --runs 5 'bundle exec rspec'
Benchmark 1: bundle exec rspec
Time (mean ± σ): 127.121 s ± 0.743 s [User: 90.705 s, System: 11.023 s]
Range (min … max): 126.002 s … 127.780 s 5 runsCucumber
(Migrate_to_ferrum) hyperfine --runs 5 'bundle exec cucumber'
Benchmark 1: bundle exec cucumber
Time (mean ± σ): 165.294 s ± 1.112 s [User: 112.951 s, System: 20.299 s]
Range (min … max): 164.166 s … 166.902 s 5 runs
selenium-webdrivers
Rspec
(master) hyperfine --runs 5 'bundle exec rspec'
Benchmark 1: bundle exec rspec
Time (mean ± σ): 121.184 s ± 0.684 s [User: 83.846 s, System: 8.371 s]
Range (min … max): 120.355 s … 122.083 s 5 runsCucumber
(master) hyperfine --runs 5 'bundle exec cucumber'
Benchmark 1: bundle exec cucumber
Time (mean ± σ): 156.351 s ± 0.834 s [User: 103.068 s, System: 22.487 s]
Range (min … max): 155.059 s … 157.337 s 5 runs
Сравнительная таблица:
Driver |
RSpec |
Cucumber |
---|---|---|
Selenium |
120.355 s … 122.083 s |
155.059 s … 157.337 s |
Cuprite |
126.002 s … 127.780 s |
164.166 s … 166.902 s |
Легенда:
Selenium - тесты с использованием драйвера selenium-webdrivers и Chrome
Cuprite - тесты с использованием драйвера cuprite и Chrome
Результаты, мягко говоря, неожиданные.
Близкие результаты Rspec определяются тем, что шагов с capybara там немного.
А вот для cucumber - половина шагов использует capybara.
Еще немного о странностях
Дальнейшее изучение проблемы с быстродействием драйвера ferrum привело к совершенно неожиданным результатам.
Одни и те же тесты в одном и том же окружении при смене версии браузера ведут себя совершенно по разному.
Для примера:
Версия браузера 108.0.5359.98 (Официальная сборка), (64 бит) - у коллеги на машине, linux
Падает один тест, который до этого не падал. Ошибка связана с тем, что не работает функция onclick. Возможно в этой версии браузера headless еще "старой" конструкции.
Версия 114.0.5735.198
все тесты выполняются без ошибок.
Google Chrome 115.0.5790.102 - последняя на текущий момент.
начали падать ДВА теста. Стабильно. На разных (двух) машинах, с MacOS и Linux. При этом попытка "разобраться", в чем там дело, завершилась несколько неудачно. Эти же тесты, но запущенные по ОДНОМУ - не падают вообще.
Предварительные выводы
Плюсы:
Возможность использования дополнительных инструментов для позиционирования, заполнения, анализа страницы
Отладка - возможность debug с текущей страницей - это просто замечательно. Подробности см. (https://github.com/rubycdp/cuprite#debugging)
Большое кол-во дополнительных полезных функций, как то ожидание ответа по AJAX, поиск по css и т.д. Справедливо будет отметить, что все эти "дополнительные" методы относятся к драйверу ferrum, а не к cuprite. Примерно так же можно использовать аналогичные методы selenuim, так что этот плюс можно считать весьма условным.
Минусы:
Поведение с разными версиями браузера ???
Быстродействие ???
Пока полученные результаты не позволяют сделать вывод о целесообразности замены selenium-webdrivers на ferrum.
Вполне возможно, что описываемые результаты увеличения быстродействия в разы связаны с какими то иными причинами.
Возможно проблема в том, что именно тестируется с помощью capybara.
Используемые нами тесты - это стандартные интеграционные тесты и не включают тестирование интерфейса как такового.
Активно используется поиск и заполнение полей, чек-боксов, выбор из списков, управление JS компонентами типа редактор tinyMCE и т.д.
Все тестируемые компоненты форм требуют авторизации, здесь используется стандартный helper от devise и в случае selenium-webdrivers, и в случае ferrum.
Вполне возможно, что быстродействие можно будет увеличить за счет использования предоставляемого механизма управления сессиями и отказа от использования sign-in.
Но это уже несколько иная ситуация, тем более, что при наличии различных ролей проблема не будет решена.
А проводить тестирование под условным "суперпользователем" как то не очень логично, особенно, если тестируются ограничения этого доступа.
Полученные результаты не позволяют сделать вывод о целесообразности замены используемого драйвера selenium-webdrivers на ferrum по состоянию разработки на текущий момент.
ferrum (0.13)
cuprite (0.14.3)
Rails 7.0.6