Тестирование пользовательских сценариев с помощью Ferrum

dmd406d0-loyyrtyzow7q2astsg.jpeg

Привет, дорогие хабражители!

Меня зовут Вадим, я представляю команду внедрения проектов группы компаний Bimeister.

В этой статье я поделюсь нашим опытом разработки автотестов для тестирования пользовательских сценариев работы с нашей платформой c помощью ruby gem — Ferrum.

Конечно, в нашей компании уже есть большая и дружная команда тестирования в группе разработки, которые покрывают тестами каждый релиз, с разной степенью автоматизации в рамках своих потребностей и KPI.

Мы же, как последняя миля перед заказчиком, поставили себе целью создать автотесты, которые:


  1. Покроют ключевую бизнес-функциональность наших заказчиков
  2. Позволят за минимальное время дать заключение о допуске релиза к установке в контур заказчика
  3. Создать понятный отчет для всех сторон с заключением об успешности/ошибках при тестировании релиза.


Проверка гипотезы

Для проработки гипотезы мы набросали простой тест-план для нашей задачи

Данный пример, лишь самая малая часть функциональности нашей платформы.

Для пробы пера взяли следующий стек:


  • ruby 3.2.2 (rbenv)
  • VM на RedOS Муром
  • Gemfile:
    • ferrum
    • dotenv
    • faker

А также logger, стандартный класс ruby, для логирования действий приложения

От приложения на рельсах на данном этапе отказались, но его создание есть в ближайших планах


Почему Ferrum

При выборе инструмента мы исходили из простоты работы с браузером, отсутствия дополнительных компонентов (web-driver) и скорости работы. Поэтому отпали Selenium и Playwright

Ferrum работает напрямую с CDP (Chrome DevTools Protocol), что освобождает от установки драйверов и позволяет контроллировать браузеры на основе Chromium напрямую. На хабре уже был обзор Ferrum

Отметим что Ferrum работает в 5–10 раз быстрее чем другие фреймворки.

Остальные браузеры (Firefox, Safari) мы не брали в расчет — у текущих заказчиков используются только Chromium подобные браузеры. Остальные браузеры тестируют коллеги из команды разработки.


Реализация

Поскольку для первого прогона у нас чистый ruby делаем:

bundle init
bundle add ferrum faker dotenv

Структура приложения будет выглядеть так:


  • корень приложения
    • main.rb — Основной файл приложения
    • lib
    • input_data.rb — Генерация данных для ввода в систему
    • method_utils.rb — Класс MethodUtils c перечнем методов для взаимодействия с интерфейсом системы
    • modules
    • management.rb — Модуль ManagementMethods с набором методов для взаимодействия с модулем администрирования системы
    • object_model.rb — Модуль ObjectModelMethods с набором методов для управления объектной моделью системы
    • process.rb — Модуль ProcessMethods c набором методов для управления бизнес-процессами системы
    • project.rb — Модуль ProjectMethods с набором методов для управления проектами в системе
  • .env — Файл с переменными окружения для хранения адреса целевого стенда, логина, пароля и других настроек приложения
  • Gemfile
  • Gemfile.lock

При первом подходе для ожидания загрузки всех ресурсов страницы пользовались методом sleep, однако он не безопасный, поскольку если ожидание закончится, а ресурсы не загружены — приложение завершится с ошибкой. Из ситуации вышли написав небольшой метод для проверки завершения загрузки страницы:

def wait_for_selector(selector, timeout = 10)
  start_time = Time.now
  element = @browser.at_xpath(selector)

  until element || Time.now - start_time > timeout
    sleep 0.1
    element = @browser.at_xpath(selector)
  end

  unless element
    @logger.error("Элемент #{selector} не загружен в течении #{timeout} секунд(ы)")
    abort("Ресурсы страницы не загружены в течении #{timeout} секунд(ы)")
  end
 end

Пример файла main.rb

require 'ferrum'
require 'faker'
require 'dotenv/load'

require_relative 'lib/input_date'
require_relative 'lib/method_utils.rb'

logger = Logger.new('logs/developer.log')
browser = Ferrum::Browser.new(headless: true, window_size: [1450, 850])
test = MethodUtils.new(browser, logger)

begin
  property_params = PARAMS_PROPERTY_CREATE
  property_params_update = PARAMS_PROPERTY_UPDATE
  test.authorization
  test.open_administrations_menu("Объектная модель")
  test.open_secondary_menu("Свойства")
  test.create(property_params)
  test.update(property_params, property_params_update)
  test.delete(property_params_update)
end

Здесь мы инициализируем экземпляр logger, ferrum и Модуль MethodUtils. Далее вызываем MethodUtilsпеременной test и поскольку модуль связан с остальными модулями через require_relative — обращаемся к методам модулей из папки Modules и идем по написанному сценарию тестирования.

Пример работы приложения

t7r5mzb5xh5fwqpwg_yzztya1ue.png

Процесс на схеме показывает работу приложения:


  1. Инициализируем в main.rb экземпляр Ferrum::Browser.new и Logger.new
  2. Передаем инициализированные экземпляры логгера и ferrum в модуль MethodUtils
  3. В свою очередь MethodUtils передает дальше экземпляры в другие модули приложения
  4. Экземпляр Ferrum::Browser.new вызывает через WebSocket инициализацию нового окна Сhrome через CDP
  5. В приложении идет выполнение логики работы с браузером
  6. После выполнения приложения Ferrum дает сигнал на завершение работы окна браузера

Пример Лога успешного выполнения тестов

I, [2023-07-17T16:54:47.112595 #17795]  INFO -- : Выбран верный провайдер (Локальный)
I, [2023-07-17T16:54:47.128303 #17795]  INFO -- : В поле 'Логин' введен логин
I, [2023-07-17T16:54:47.150329 #17795]  INFO -- : В поле 'Пароль' введен пароль
I, [2023-07-17T16:54:47.426656 #17795]  INFO -- : Кнопка 'Войти' нажата
I, [2023-07-17T16:54:50.373433 #17795]  INFO -- : Кнопка 'Администрирование' НАЖАТА
I, [2023-07-17T16:54:50.750440 #17795]  INFO -- : Кнопка администрирования 'Объектная модель' НАЖАТА
I, [2023-07-17T16:54:50.802920 #17795]  INFO -- : Кнопка меню (Связи) нажата
I, [2023-07-17T16:54:50.943513 #17795]  INFO -- : Нажата кнопка создания 'Связи'


Что дальше

В следующих статьях мы продолжим разработку приложения для тестирования пользовательских сценариев:


  1. Перейдем на Ruby on Rails,
  2. Добавим в Faker методы генерации для наших нужд,
  3. Релизуем пользовательский интерфейс,
  4. В интерфейсе реализуем:
    1. Выбор стенда для тестирования, и тестов для объектной модели заказчика
    2. Выбор количества экземляров тестов (параллельное выполнение, нагрузочное тестирование)
    3. Выбор количество пользователей, проектов, процессов, объектов
  5. Добавим генерацию отчета по результатам тестирования,
  6. Поставим приложение на мониторинг,
  7. Добавим авторизацию и ролевую модель,
  8. Передадим команде аналитиков приложение автотестов под согласованные тест-планы наших заказчиков,
  9. Проработаем возможность проводить ПСИ (приемо-сдаточные испытания) с использованием Capybara+Cuprite+Ferrum.

На связи была команда Bimeister, не переключайтесь!

© Habrahabr.ru