Rails7. Ferrum для тестов приложения

от автора

Много тестов — это хорошо, особенно если они еще и по делу.

Но много тестов — это время, которое они занимают в процессе выполнения. И если его можно уменьшить — почему бы это не сделать.

Вдохновившись описанными получаемыми результатами:

, пробуем использовать 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 runs

  • Cucumber
    (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 runs

  • Cucumber
    (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

Используемые источники


ссылка на оригинал статьи https://habr.com/ru/articles/751674/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *