Привет! Меня зовут Евгений Константинов. Я занимаюсь разработкой инструментов автоматического тестирования в Яндексе. В этой статье хочу рассказать про историю создания инструмента Testplane, который предназначен для тестирования пользовательских сценариев во фронтенде и теперь доступен в опенсорсе.
Testplane поможет вам:
протестировать разные сценарии в любом браузере;
проверить вёрстку с помощью скриншотного тестирования;
выполнить тестирование ваших React-компонентов;
запустить клиентские unit-тесты в контексте браузера.
Как всё начиналось
Всё началось в далёком 2014 году, когда внутри Яндекса развивалась библиотека общих компонентов под названием «Лего», а снаружи — библиотека компонентов БЭМ. И там, и там реализовывались готовые блоки с вёрсткой, которые каким-то образом нужно было тестировать. Самый подходящий для этого способ — сделать скриншот компонента и сравнить его в формате «было/стало». Но после долгих поисков в интернете мы не нашли готового решения, с помощью которого можно было бы легко и быстро написать тесты на JavaScript, выполнить их в браузере и посмотреть результаты в отчёте.
В этот момент и появилась Gemini — утилита для регрессионного тестирования внешнего вида веб-страниц. У инструмента были максимально простой (но в то же время ограниченный) API, собственная реализация скриншотного сравнения (в том числе и патент на способ тестирования) и отчёт для анализа результатов. Этого с головой хватило, чтобы покрыть все основные кейсы при тестировании интерфейсов.
Но время шло, и требования к тестированию менялись. Одних скриншотов стало не хватать — хотелось большего. А именно — тестировать реальные пользовательские сценарии. Да, большинство сценариев можно проверить с помощью скриншотов (например, что в поля вставили нужные данные), но очевидно, что такое тестирование избыточно и не всегда удобно. Поэтому в 2016 году мы опубликовали новый инструмент Hermione.
Этот инструмент представлял из себя композицию из трёх инструментов: Gemini, Webdriverio и Mocha. В этой связке от Gemini мы получили скриншотное тестирование со всеми нашими наработками, от Webdriverio — богатый API по взаимодействию с браузером, а от Mocha — привычный для пользователей интерфейс написания тестов.
Почему выходим в опенсорс
Долгое время основными пользователями Hermione были внутренние сервисы, и его продвижением снаружи мы никогда особо не занимались, хоть инструмент и был в опенсорсе с 2016 года. Для новых разработчиков, приходящих снаружи, это был совершенно новый инструмент. К тому же поиск по слову Hermione чаще всего выдаёт в основном только историю героини книг Джоан Роулинг.
В общем, оказывается, что для выхода в опенсорс недостаточно просто запушить исходники на GitHub (сюрприз-сюрприз). Поэтому в этот раз к тому же выбору нового названия мы отнеслись серьёзно и проанализировали его на наличие торговой марки, домена для сайта, стилистики и прочие детали.
Подробно про то, как правильно выходить в опенсорс, я описывать не буду. Вместо этого просто приглашаю всех заинтересовавшихся смотреть трансляцию Yandex Open Source Jam, на которой вы сможете узнать в том числе нашу историю. Однако скажу, что в результате ребрендинга появился новый продукт под названием Testplane.
Кто такой этот ваш Testplane и в чём его особенность?
На данный момент наш инструмент позволяет решать сразу несколько задач тестирования — проверять пользовательские сценарии в браузере, находить баги в верстке с помощью скриншотного тестирования, писать тесты на компоненты (например, на React) или запускать обычные unit-тесты в браузере.
Сами тесты можно писать в знакомом для многих синтаксисе. Например, так выглядит простой тест:
describe("test", () => {
it("example", async ({browser}) => {
await browser.url("https://github.com/gemini-testing/testplane"); // Открываем тестируемый урл
const aboutSection = await browser.$(".f4.my-3"); // Ищем нужный элемент на странице
await expect(aboutSection).toHaveText("Browser test runner based on mocha and wdio"); // Библиотека ассертов доступна из коробки
await aboutSection.assertView('plain-view'); // С помощью скриншота проверяем вёрстку
});
});
Плагинная система
Для нашего инструмента довольно просто написать свой плагин, в котором можно реализовать свою кастомную логику. Это может быть свой репортер, поднятие dev-сервера перед началом теста или отправка статистики результатов тестов. Подробнее про доступные события можно почитать в документации. Кроме того, с помощью плагинов вы можете добавлять даже кастомные CLI-команды и опции. Например, так будет выглядеть мини-плагин, который будет в рантайме отключать нестабильные тесты при их падении:
export default (testplane: Testplane) => {
const someStatStorage = require('your-stat-storage-client');
// Перехватываем событие, чтобы отключить нестабильный тест
testplane.intercept(testplane.events.TEST_FAIL, ({event, data: test}) => {
// Проверяем, является ли тест нестабильным
const isFlaky = someStatStorage.getTestStat(test.fullTitle()); if (isFlaky) {
// Отключаем тест и указываем причину отключения
test.skip({reason: 'This test was disabled automatically'});
// Вместо события FAIL бросаем событие PENDING (), на которое могут подписаться другие плагины
return { event: testplane.events.TEST_PENDING, data: test };
}
// Если перехватывать событие не нужно, достаточно вернуть любое falsey-значение
return;
});
};
Масштабируемость
На данный момент с помощью нашего инструмента внутренние сервисы в Яндексе запускают десятки тысяч тестов, которые выполняются менее чем за 10 минут. Это достигается как за счёт параллельности выполнения тестов в рамках одного запуска, так и за счёт того, что пак тестов можно разбить на любое количество чанков, которые могут быть запущены на разных машинах в CI. При этом на выходе пользователь анализирует единый HTML-отчёт, в котором будут отображены тесты из всех чанков.
Скриншотное тестирование + UI для работы со скриншотами
Скриншотное тестирование — неотъемлемая часть при тестировании вёрстки сервиса. Соответственно, этому типу тестирования мы уделяем особое внимание: у нас реализована своя библиотека сравнения looks-same с широкими возможностями, удобный UI для работы со скриншотами (сравнение, поиск дифов, обновление скриншотов) и автоматическое тестирование Storybook-компонентов (тесты генерируются автоматически в рантайме, а вам нужно будет только принять эталонные скриншоты в UI):
Пошаговое выполнение тестов с помощью REPL-режима
Для удобства написания тестов (а также их дебага) в нашем инструменте есть REPL-режим. С его помощью пользователь может пошагово (построчно) выполнять код теста, чтобы проверить его работоспособность или найти проблемное место. В таком режиме пользователь в рантайме видит процесс выполнения своего теста в локально поднятом браузере или даже в удалённом браузере через VNC. Главная особенность заключается в том, что такой вариант тестирования доступен абсолютно для любого браузера: и для Chrome, и даже для удалённо поднятого iOS-устройства.
Как попробовать
Чтобы настроить Testplane у себя в проекте или просто собрать тестовый проект, достаточно выполнить команду в терминале:
npm init testplane some-project
// Если не указать директорию, то проект будет развёрнут в текущей директории
После её выполнения в указанной директории установятся все необходимые npm-зависимости, сгенерируется конфиг для запуска тестов с предустановленными плагинами и добавится пробный тест.
Запустить тесты можно с помощью CLI-команды npx testplane
или через UI, который можно открыть командой npx testplane gui
.
Пробуйте Testplane, приносите фидбек в issues и свои PR. А ещё смотрите трансляцию Yandex Open Source Jam, чтобы узнать больше про опенсорс — ждём вас!