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


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


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


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


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


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

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


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


название кейса Роль Описание шагов
Аутентификация Администратор/Пользователь Аутентификация пользователя в системе
Проверка доступа к разделам Процессы Управление Объектная модель Администратор Пройти по меню системы, убедится, что разделы доступны открываются, в открытых вкладках, можно создавать/изменять объекты системы без ошибок 1.Процессы Проверить создание/изменение/удаление процессов 2.Управление Проверить создание/изменение/удаление для ролей, пользователей, групп. Проверить Журнал, то, что действия в системе фиксируются в журнале 3.Объектная модель Проверить создание/изменение/удаление для Свойств, Справочников, Интерфейсов, Классов, Структур, Связи
Управление ролями пользователей Администратор 1. Добавление/удаление ролей на проект Перейти в проект, на вкладке роли, удалить несколько ролей в проекте, добавить другие роли, убедиться, что изменения сохранились 2. Добавление/удаление пользователей в проект Перейти в проект, на вкладке пользователи, удалить несколько пользователей в проекте, добавить других пользователей, убедиться, что изменения сохранились 3. Добавление ролей пользователям в проекте Перейти в проект, на вкладке пользователи, удалить у нескольких пользователей роли, добавить роли другим пользователям роли, убедиться, что изменения сохранились
Проверка доступа в проекте Пользователь Пройти в проект проверить доступ к вкладкам проекта, доступность информации на вкладках, отсутствие ошибок на вкладках при просмотре информации Основные вкладки 1.Рабочий стол 2.Сцена 3.Архив 4.Документооборот 5.Реестр замечаний 6.Отчеты по процессам 7. Диспетчер На перечисленных вкладках, проверить создание/удаление/изменение папок/карточек документов/задач документооборота/замечаний/отчетов
Проверка импорта/экспорта Пользователь Пройти на вкладку Архив и реестр замечаний, проверить функции импорта/экспорта документации и реестра замечаний
Работа в Архиве Пользователь Пройти на вкладку Архив Нажать кнопку кнопку "Создать", создать карточку документа, прикрепив файл к карточке В созданной карточке документа перейти в кнопку "Редактирование" изменить несколько свойств, сохранить карточку: Как новую версию Как текущую версию Выбрать карточку файла или несколько, нажать кнопку кнопку "Экспортировать", выполнить экспорт, проверить выгруженные файлы на корректность Выбрать одну или несколько карточек файлов и нажать кнопку "Удалить", проверить, что удаление завершиться успешно Выбрать одну или несколько карточек файлов и нажать кнопку "Создать задачу", проверить, что удаление завершиться успешно

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


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


  • 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 и идем по написанному сценарию тестирования.


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



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


  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, не переключайтесь!

Комментарии (4)


  1. mpetrunin
    20.07.2023 06:45

    А что думаете про Playwright?

    К нему неофициальный gem для ruby и для capybara написали: https://dev.to/yusukeiwaki/using-playwright-in-ruby-rails-2km0

    Из явных плюсов Playwright: поддержка Firefox не только Chromium.

    Пилит команда Microsoft


    1. voody77 Автор
      20.07.2023 06:45

      Смотрели Playwright, отпал по причине дополнительных зависимостей (web-driver, nodejs) и скорости работы, в отличии от ferrum. Но playwright, в свою очередь, оказался быстрее Selenium.

      Про поддержку Firefox - я написал, нам не требуется на этом этапе.


      1. mpetrunin
        20.07.2023 06:45

        Насколько у вас получился Ferrum быстрее Playwright?

        И разве Playwright не использует CDP в случае Chromium?


        1. voody77 Автор
          20.07.2023 06:45

          На наших тестах в 6 раз быстрее.

          Playwright использует свой драйвер, архитектура из гайда на картинке: