Вступление

Привет! Меня зовут Вячеслав, я инженер по автоматизации тестирования в компании ROWI.Tech.
В ходе автоматизации тестирования пользовательских интерфейсов зачастую используется такой подход как визуальное тестирование. Он позволяет поддерживать стабильность и отсутствие ошибок в отображении страниц.
Одним из инструментов, предоставляющих возможность автоматизации данного вида тестирования, является Playwright.
В этой статье я расскажу о работе с визуальным тестированием в рамках упомянутого инструмента, как мы справились со сложностями хранения эталонных скриншотов и автоматизировали их обновление.
Содержание
Визуальные проверки Playwright.
Облачное хранилище для эталонных скриншотов.
Обновление скриншотов.
Автоматизация обновления эталонных скриншотов.
Визуальные проверки в Playwright
Данный инструмент предоставляет утверждение из “коробки” для визуальных проверок - toHaveScreenshot
. Можно визуально сравнивать как страницы, так и отдельные элементы на ней.
Возможные настройки утверждения:
Отключение анимаций.
Передача стилевых файлов.
Настройка маски для динамических элементов.
Также помимо настройки самого утверждения можно указать некоторые настройки глобально:
Максимальная разница в результатах по сравнению с эталоном в пикселях и долях.
Путь до скриншота
С полным списком настроек можно ознакомиться в официальной документации Playwright.

Облачное хранилище для эталонных скриншотов
Playwright сохраняет скриншоты в установленной директории проекта. Мы можем определить необходимое расположение согласно установленной структуре с помощью указания шаблона пути до необходимой директории в конфигурационном файле (playwright.config.ts
).
Это дает нам выбрать способ хранения скриншотов:
Сохранять скриншоты в проекте, публиковать их вместе с изменениями кодовой базы.
Хранить скриншоты в отдельном удалённом хранилище.
Первый подход имеет свои недостатки. Он увеличивает размер проекта и число изменяемых файлов. С ростом количества тестов увеличивается и размер репозитория.
Git LFS является расширением Git, которое применяется в работе с часто изменяющимися большими файлами, такими как изображения и наборы данных. Оно может решить проблему хранения эталонных скриншотов в проекте. Подробнее об использовании Playwright с Git LFS можно прочитать тут.

Альтернативой Git LFS являются отдельные удалённые хранилища, например облачные. Одним из таких хранилищ является объектный S3.

Мы решили использовать альтернативный подход, воспользовавшись S3 хранилищем, в котором были заведены отдельные bucket’ы для визуального тестирования и e2e-тестов.
В CI/CD мы реализовали отдельный этап, на котором в проект загружаются все необходимые файлы, используя MC образ.
Этап скачивания эталонных скриншотов
screenshot-download:
stage: screenshot-download
allow_failure: true
artifacts:
paths:
- screenshot
- static-files
reports:
dotenv: screenshot-variables.env
expire_in: 1 hour
script:
- |
PROJECT_GROUP=$(echo ${CI_PROJECT_NAMESPACE} | grep -Eo '([^\/]+)[\/]?$')
- echo "PROJECT_GROUP=${PROJECT_GROUP}" >> screenshot-variables.env
- mc alias set bucket-alias https://path-to-storage.net $BUCKET_ROWI_TEST_SCREENSHOT_ACCESS_KEY $BUCKET_ROWI_TEST_SCREENSHOT_SECRET_KEY
- mc cp --recursive bucket-alias/rowi-test-screenshot/${PROJECT_GROUP}/ screenshot
- ls screenshot
- |
if [[ ! -z $(mc ls bucket-alias/rowi-test-static-files/${PROJECT_GROUP}/) ]]; then mc cp --recursive bucket-alias/rowi-test-static-files/${PROJECT_GROUP}/ static-files
ls static-files;
fi
Обновление скриншотов
После перемещения эталонных скриншотов в облачное хранилище механизм обновления стал следующим:
Запустить Docker контейнер playwright.
Выполнить необходимые тесты с ключом update-snapshots.
В ручном режиме загрузить полученные скриншоты в S3 хранилище, используя клиент (например, s3 Browser).

Но по мере увеличения таких тестов увеличиваются и трудозатраты на актуализацию ожидаемых результатов.
Мы приняли решение реализовать механизм, с помощью которого можно было бы обновлять скриншоты прямо из отчёта о тестировании. Вдохновением для реализации послужила статья, в которой был разработан артефакт, содержащий запись теста.
Автоматизация обновления эталонных скриншотов
Мы остановились на HTML с кнопкой обновления скриншота, загружаемый в качестве артефакта.
Требования
Реализуемая страница должна обладать следующими качествами:
Кнопка должна относиться к конкретному скриншоту.
Кнопка появляется только в случае несоответствия скриншотов.
Загрузка скриншотов должна осуществляться в S3 хранилище по одному нажатию кнопки.
Актуальный скриншот должен стать эталонным.
Должна быть индикация успешной загрузки скриншота.
Реализация
Флагом несоответствия с эталонным скриншотом является наличие актуального скриншота. Это можно использовать для начала формирования артефакта.
if (matcherResult["actual"]) await attachHtmlButton(matcherResult);
После того, как стала понятна отправная точка для формирования артефакта, нужно определить зависимости, необходимые для его реализации. Такими зависимостями стали:
AWS SDK
для взаимодействия с удалённым хранилищем.Buffer
для преобразования base64 строки в объектBuffer
.
Allure предлагает широкий выбор типов приложений, одним из которых является HTML, в котором можно разместить кнопку.
Для записи артефакта используется TestInfo
объект, содержащий информацию о выполняемом тесте.
Создание артефакта представлено следующим образом:
//генерируется случайный uuid для уникального названия артефакта
//получение пути до артефакта в контексте текущего теста
const file = testInfo.outputPath(`${faker.string.uuid()}.html`);
//запись HTML-артефакта
await fs.writeFile(file,prepareHtml((await fs.readFile(matcherResult.actual, { encoding: "base64" })).toString(),`path/to/s3/expected.png`),"utf8");
//приложение HTML к артефактам текущего теста
await testInfo.attach("Upload:" + matcherResult.actual.split(/\//).at(-1).replace(".png", ""), {path: file, contentType: "text/html"});
В HTML-артефакте была создана кнопка, нажатие на которую обрабатывается с помощью функции uploadSnapshot.
HTML-кнопка
<html>
<head>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.742.0.min.js"></script>
<script src=" https://bundle.run/buffer@6.0.3"></script>
</head>
<body>
<button onclick="uploadSnapshot()">Send to S3</button>
<div id="Notification">Click button to upload</div>
<script>
async function uploadSnapshot(){
<!-- настройка подключения к S3 -->
AWS.config.update({
<!-- здесь ключи доступа к S3 -->
});
<!-- создание S3 объекта с настроенным подключением -->
var s3 = new AWS.S3({
sslEnabled: true,
});
<!-- создание Buffer объекта -->
var base64Data =
buffer.Buffer.from("${buffer}","base64");
<!-- оглашение параметров PUT запроса в S3-->
var params = {
Bucket: "название bucket’a",
Key: "путь до эталонного скриншота",
Body: base64Data,
ContentEncoding: "base64",
ContentType: "image/png",
};
try {
<!-- отправка PUT запроса в S3-->
await s3.upload(params).promise();
<!-- уведомление об успешном завершении загрузки -->
document.getElementById("Notification").textContent = "Uploaded";
} catch (error) {
console.log(error);
}
</script>
</body>
</html>

Используемые CDN были добавлены в Allure-образ, чтобы сократить время на их загрузку и обеспечить их доступность.
Выводы
Визуальное тестирование является одним из популярных видов тестирования, встречающихся в автоматизации. Правильный подход к хранению и обновлению эталонных скриншотов может значительно сократить затрачиваемые ресурсы на поддержку данных тестов.
Перемещение скриншотов в облачное хранилище позволило уменьшить размер репозитория и исключить лишние коммиты в репозиторий, связанные с обновлением скриншотов.
Реализованная кнопка позволила упростить обновление эталонных скриншотов и сделала данный процесс доступным для всех участников команды. Теперь вместо поднятия Docker контейнера с образом Playwright или скачивания с Allure отчёта и последующей ручной отправки в S3 формируется артефакт, автоматизирующий рутинные действия