Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Привет, Хабр!
Хотим поделиться краткой историей о том, как мы на одном из проектов «Рексофт» пришли к написанию автотестов, и почему сделали акцент именно на e2e-тестах.
Речь пойдет о работе с порталом крупного федерального заказчика, работающего в сфере B2B и B2C, имеющего серьезный трафик из всех регионов. Сайт писал не «Рексофт». Ресурс попал к нам на поддержку какое-то время назад. Изначально проект содержал довольно много легаси кода, тестов не было, как и документации. Требовалось сделать редизайн по новым макетам, параллельно расширяя существующую функциональность. Обычная история.
В какой-то момент мы поняли, что ручное прокликивание интерфейса стало занимать очень много времени, и решили, что пришло время для автотестов.
Перед выбором подхода к автотестам классифицировали баги по типу: их большая часть касалась именно бизнес-логики (Javascript). Багов, связанных с кроссбраузерностью или вёрсткой, было не очень много.
Итак, цель была поставлена — автоматизировать проверку бизнес-логики, т.е. заполнение и отправку форм, работу слайдеров и т.д.
В качестве базового фреймворка для тестов был выбран Jest, а для имитации действий пользователя — Puppeteer. Последний выбрали благодаря тому, что он поддерживается Google и имеет отличную документацию. Нам было вполне достаточно тестов в одном браузере (Chrome) (хотя, есть инструменты, позволяющие с помощью Puppeteer запускать тесты и в других браузерах, например, Firefox и IE). Playwright тогда ещё не было, а Selenium, чисто субъективно, казался более сложным в развертывании.
Далее кратко опишу преимущества и недостатки e2e-тестов.
Недостатки e2e-тестов
Относительно высокая сложность написания. Нужно обладать определёнными навыками, чтобы написать компактный и легкочитаемый e2e-тест.
Проблема закопаться. Я точно знаю, что желание проверить всё и вся, может привести к написанию огромного количества избыточных тестов. Как побороть эту проблему? Не стоит пытаться протестировать абсолютно все возможные кейсы, достаточно сосредоточиться на основных.
Низкая скорость прохождения тестов (в сравнении с юнит-тестами). Довольно много времени тратится на запуск браузера, ожидание загрузки страницы, завершения анимаций и прочее. Для ускорения прохождения тестов потребуется свести к минимуму число пользовательских действий, а также число загрузок новых страниц.
«Хрупкость» e2e-тестов. Что я имею ввиду? Случай, когда тест падает без видимых на то причин, а при повторном запуске успешно выполняется, или же когда к падению теста приводит незначительное изменение в верстке. С хрупкостью тестов можно бороться с помощью автоматического перезапуска теста после падения. Помогут в этом раннер jest-circus и параметр retryTimes. Это практически полностью решает проблему “ложных” падений тестов.
Преимущества e2e-тестов
Гарантии. С e2e-тестами вы получаете определенные гарантии того, что система в целом работает корректно. Юниты такой гарантии не дают. Разумеется, это не значит, что вы получаете 100% гарантию того, что у вас работает абсолютно всё. Но вы будете уверены, что по крайней мере протестированные сценарии точно работают.
Снижение рабочей нагрузки. Без тестов разработчик вынужден думать — «как бы чего не сломать». Ведь не прокликивать же весь проект после очередного коммита с правками! С тестами вы узнаете о поломке еще до того, как код будет залит на стенд.
Ускорение разработки. Благодаря снижению количества багов и устранению ручных проверок интерфейса, серьезно экономится время. Причём e2e-тесты экономят не только ваше время, но и время тестировщиков (позволяя им заводить меньше багов, меньше коммуницировать, выясняя их детали и т. д.), время аналитиков (понятные тесты — отличная документация, отвечать на вопросы аналитиков вы будете намного быстрее).
Ускорение рефакторинга. При рефакторинге js, e2e-тесты не придется переписывать. Да и рефакторинг в вёрстке тоже редко приводит к их переписыванию.
Нет зависимости от кодовой базы и js-фреймворка. Вы можете написать e2e-тесты даже к легаси коду, что поможет быстрее его отрефакторить. При этом вы практически не зависите от js-фреймворка, т.к. в тестах оперируете только сущностями браузера.
Лайфхаки
1. Для ускорения написания первых тестов можно записывать действия пользователя с помощью Headless recorder или с помощью встроенных в Chrome инструментов.
2. Если требуется проверить несколько наборов данных в рамках одного кейса и руки тянутся написать for внутри теста, используйте jest-each. Эта библиотека позволит прогнать несколько наборов данных в одном кейсе, сохранив читаемость кода:
each`
url | selector | expectedIsVisible
${'/page1.html?land'} | ${'.js-order-button'} | ${true}
${'/page1.html'} | ${'.js-order-button'} | ${false}
${'/page2.html?land'} | ${'.js-order-button'} | ${true}
${'/page2.html'} | ${'.js-order-button'} | ${false}
`.it('Отображение кнопок заказа на странице $url', async ({ url, selector, expectedIsVisible }) => {
await page.goto(`${SERVER_URL}${url}`, {
waitUntil: 'networkidle2',
timeout: 0
});
expect(await isVisible(page, selector)).toEqual(expectedIsVisible);
});
3. В случае возникновения ошибок, puppeteer не всегда корректно подсвечивает строку с ошибкой. Поэтому следует проверить код перед ошибочной строкой, часто ошибка кроется именно там.
4. Puppeteer позволяет запускать браузер с различными флагами, что иногда очень полезно (chrome://flags/). Ниже пример запуска браузера с отключенным флагом SameSite by default cookies
puppeteer.launch({
headless: true,
slowMo: 80,
args: [
'--disable-features=SameSiteByDefaultCookies'
]
});
В качестве заключения
Написание e2e-тестов занимают около 5-10% от времени написания фичи. На фиксы багов уходило сильно больше времени, так что оно того стоило. Несмотря на ряд недостатков, e2e-тесты позволяют значительно ускорить процесс разработки и обрести уверенность в том, что основная функциональность системы работает.
Разумеется, при внедрении e2e-тестов для фронтенда необходимо учитывать специфику вашего проекта. Спасибо за внимание!