Протестировать за 60 секунд

49 2

Одним из ключевых этапов модификации системы является тестирование. Чем обширнее и чаще проводится тестирование, тем выше качество продукта. В идеальном представлении проверяется абсолютно весь функционал, что сводит вероятность появления ошибки к минимальному значению. Но каждый тест требует времени и также можно утверждать: чем обширнее и чаще проводится тестирование, тем больше трудозатраты. И как тогда быть?

Как минимум после каждого опубликованного пакета тестируется требуемый функционал. А как быть с регрессионными тестами, которые информируют команду: не сломали ли их изменения что-то в другой части системы? Получается после каждой модификации нужно проверить и основной функционал: создание разных документов, создание и изменение записей справочников, отправка задач и т.д. Сколько раз нужно кликнуть мышкой, чтобы протестировать, например, задачу на согласование по регламенту?..

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

Что будем использовать?

На данный момент в рамках исследования CI/CD на некоторых наших проектах настроена автоматическая сборка и публикация пакета при срабатывании триггера, например, при каждом коммите в определенной ветке. Настройка CI/CD позволяет к сборке и публикации также добавить автоматическое тестирование, возможности которого и посвящена данная статья.

Голоса в голове заставляют меня создать модель тестировщика, который будет нажимать на определенные кнопки в определенной последовательности и предоставлять результат проделанных действий. Для этих целей существует множество инструментов: Selenium, Puppeteer, Protractor, Cypress и другие.

Но мне захотелось попробовать относительно свежий Playwright, который как раз позволяет имитировать действия пользователя. Playwright - это библиотека Node.js для автоматизации Chromium, Firefox и WebKit с помощью одного API. Полный список возможностей Playwright лучше почитать на официальном сайте, я лишь кратко напишу, что Playwright кросбраузерный (Chromium, WebKit, Firefox), кросплатформенный (Windows, Linux и macOS) и крос многоязычный (TypeScript, JavaScript, Python, .NET, Java).

Постановка задачи

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

Для решения задачи буду использовать расширение Playwright для VS Code, установка которого занимает пару минут. После установки генерируется пробный тест, запустив который убеждаемся, что Playwright работает. Собственно, можно приступать к написанию тестов.

Пробный запуск

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

// Проверить и сменить локализацию
async function CheckAndChangeLanguage (page) {
  let engLocator = page.getByText(/English/);
  let ruLocator = page.getByText('Русский (Россия)');

  if (engLocator.isVisible()) {
    await engLocator.click();
    await expect(ruLocator).toBeVisible();
    await ruLocator.click();
  }
}

Поиск элементов на странице может осуществляться по заголовку, тексту, селектору и т.д. Для более точного поиска можно опираться на guid контрола/действия. Playwright также поддерживает различные действия пользователя от клика мыши до нажатия сочетания клавиш и выделения текста, что также может пригодиться.

Сценарий тестирования

Далее аналогичным образом пишу оставшийся сценарий теста. Конечно же, не вручную, а с помощью встроенного инструмента Codegen, который позволяет записывать действия в браузере и преобразовывать их в код. Также необходимо в паре мест добавить задержки, так как Playwright слишком быстр и сервер за ним не успевает. Раскидав код по функциям получился следующий сценарий.

const { test, expect } = require('@playwright/test');
let id = 0;

test('incomming.test.js', async ({ page }) => {
  await page.goto('http://localhost/client/#/');

  await CheckAndChangeLanguage(page);
  await LogIn(page, 'k.sannikov', '11111');
  await CreateIncomingLetter(page);
  await RegisterIncomingLetter(page);
  await SendToReview(page);
  await LogOut(page);
  await LogIn(page, 'a.sannikov', '11111');
  await OpenTask(page, parseInt(id.match(/\d+/)));
  await LogOut(page);
});

Если подробнее, то заходим в локальный RX, меняем локализацию, выполняем вход с тестового пользователя, создаем входящее письмо с минимальным набором данных и версией, регистрируем, далее отправляем задачей на рассмотрение документа и выходим из системы, выполняем вход под вторым тестовым пользователем, открываем и выполняем задание с требуемым результатом, разлогиниваемся. Поиск задания осуществляется по его идентификатору. На требуемых этапах делаем скриншоты страницы.

Для примера вот листинг функции CreateIncomingLetter:

// Создать входящее письмо
async function CreateIncomingLetter (page) {
  await page.getByText('Создать').click();
  await page.getByText('Прочее…').click();
  await page.getByPlaceholder('Искать в списке…').fill('Входящее письмо');
  await page.getByText('Входящее').click();

  await page.getByRole('button', { name: 'Версии' }).click();
  await page.locator('#version-panel').getByText('Создать из шаблона').click();
  await page.getByText('Шаблон входящего письма').click();
  await new Promise((r) => setTimeout(r, 1000));

  await page.locator('textarea').nth(1).click();
  await page.locator('textarea').nth(1).fill('PlayWright');

  await page.locator('div').filter({ hasText: /^КорреспондентДата от№В ответ наПодписалИсполнитель$/ }).getByRole('combobox').first().click();
  await page.locator('div').filter({ hasText: /^КорреспондентДата от№В ответ наПодписалИсполнитель$/ }).getByRole('combobox').first().fill('aleksander');
  await page.getByText('Sannikov Aleksander').click();
  await page.getByTitle('Сохранение изменений (Ctrl+S)').click();
  await new Promise((r) => setTimeout(r, 1000));
}

Выходные данные

Для демонстрации результатов попросим Playwright записывать видео. Выглядит довольно эффектно. Приглашаю к просмотру, оно того стоит: TestRecordng.mp4.

Описанный выше тест занял 30 секунд. В папке отчета лежат следующие скриншоты:

В демонстрационных целях я создал всего один тест, но таких тестов может быть значительно больше. По каждому тесту формируется отчет с полным набором выполняемых команд, прикрепленными скриншотами и записью видео (опционально). Отчет свидетельствует об успешном или неуспешном прохождении и наличии ошибок с указанием места, в котором они произошли. Благодаря гибкой настройке CI/CD можно прогонять полный набор тестов сразу после публикации пакета, а при наличии ошибок отправлять тестировщику отчет.

В заключение

Написание тестов в Playwright очевидно занимает больше времени, чем несколько ручных прогонов. Соответственно, внедрение подобной практики имеет смысл на начальных этапах проекта с долговременной перспективой.

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

49
Авторизуйтесь, чтобы оценить материал.
8

Константин, приветствую. Отличная статья. Спасибо за подробную, развернутую информацию касаемо создания и встраивания тестов. Есть вопрос касаемо CI/CD, а именно каким образом формируется xml файл для создания пакета выгрузки, если допустим изменения внесли только в один проект (включая все зависимости и т.д.)? Или каждый раз выгружается весь проект на стенд? Сможете рассказать более подробно?

Алексей Присяжный

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

Авторизуйтесь, чтобы написать комментарий