Тестируем веб-приложение с Cypress
Всем привет, сегодня я рад представить материал по end-to-end (e2e) тестированию. Данный вид тестирования поможет вам сэкономить время, если у вас есть задачи по проверке работоспособности веб-приложения.
Статья рассчитана на новичков в программировании (как начинающих разработчиков, так и начинающих тестировщиков).
End-to-end тестирование - это вид тестирования, при котором компьютер максимально близко к реальности эмулирует поведение пользователя. То есть, ваше web-приложение загружается в браузере, затем нажимаются кнопки, происходят переходы по ссылкам, страница прокручивается и так далее. При данном подходе backend не "мокается", таким образом все http-запросы происходят в реальном времени.
Можно провести аналогию, что за компьютером сидит робот и нажимает кнопки в указанном порядке.
Содержание:
Введение
Не скоро проза складывается, да скоро тесты пишутся. Распрощаемся с музой и посмотрим на исходный код. На выбор у нас два репозитория:
- счетчик на React (потому что React популярный, и спасибо ему за все! За основу взят репозиторий create-react-app).
- счетчик на Elm (потому что Elm - это лучшее, что со мной случилось во фронтенде на данный момент. За основу взят репозиторий create-elm-app).
Также два репозитория докажут нам на деле, что Cypress'у не важно на чем написано приложение.
В master ветке находится логика и верстка, а тесты мы сейчас с вами добавим.
Установка Cypress
NPM / Yarn на ваше усмотрение. Я буду использовать npm и устанавливать Cypress как локальную зависимость. Все примеры я выполнял на macOS.
Установка может занять продолжительное время.
Добавляем скрипт для запуска тестов
Запустить любой "исполняемый" скрипт можно командой:
Но это не удобно, поэтому давайте добавим в package.json в секцию scripts новую строку:
Теперь наши тесты можно запускать с помощью команды:
Попробуйте выполнить команду. В первый раз выполнение займет больше времени, чем обычно (так как Cypress скачает все необходимое для работы).
Если установка прошла успешно, у вас откроется окно с тестами-примерами, которые были добавлены командой разработчиков Cypress. Рекомендую их запустить, чтобы ознакомиться с возможностями инструмента.
Можно выбрать Electron 83 (Chromium), Google Chrome (настоящий) или Firefox. Я оставлю Electron 83 по умолчанию.
Перед тем, как мы начнем писать наши тесты, давайте удалим все тесты-примеры из директории cypress/integrations/examples.
Добавляем тесты
Принцип простых тестов на Cypress сводится к тому, чтобы найти элемент и (если нужно) произвести над элементом какое-нибудь действие. Очень похоже на тот код, который мы писали во времена jQuery.
Наш план автоматического тестирования будет состоять из следующих пунктов:
- убедиться, что приложение ("сайт") на localhost открылось.
- убедиться, что у нас есть кнопка "+".
- убедиться, что у нас есть кнопка "-".
- убеиться, что результат "ноль".
Начнем с первого пункта - проверки, что приложение загрузилось.
Создадим новый файл в директории с проектом:
cypress/integration/main.js
context (вы можете так же использовать describe) - это название категории (группы) ваших тестов. it - элемент в группе, то есть сам тест.
Сразу же запустим наш тест...
Почему ошибка? Потому что мы забыли запустить приложение.
Давайте еще раз повторим: end-to-end тестирование - это "эмуляция" действий реального пользователя в реальном браузере. Мы можем посетить "vc.ru" и кликнуть на заголовок первого материала, если мы хотим это протестировать. Но, так как мы тестируем наше приложение в режиме разработки, то нам необходимо до запуска e2e-тестов запустить наше приложение и оставить его запущенным. Поэтому, запустите приложение в соседней вкладке терминала и запустите тесты вновь.
Приложение загрузилось, порядок. Можно заниматься поиском элементов. Для этого, как советует раздел документации, добавим тестируемым элементам data-cy аттрибут (привожу примеры на react, elm код здесь)
src/App.js
Данный атрибут нам нужен, чтобы наверняка найти нужный элемент. Давайте напишем тесты для проверки, действительно ли кнопки "+" и "-" отрисованы на странице.
cypress/integration/main.js
Порядок. Мы нашли элементы, этого достаточно.
Для проверки, что "результат" при загрузке приложения равен нулю, нам нужно не только найти DOM-элемент, но также посмотреть чему равно его текстовое содержимое.
(троеточие означает, что часть кода скрыта для краткости)
cypress/integration/main.js
Проверяем:
Обратим внимание на синтаксис: сначала мы нашли элемент (cy.get), затем проверили его с нашим "утверждением/ожиданием" (в англ - assertion). Такой подход проверки результата с ожиданием используется в тестах повсеместно. Все возможные "ожидания" и примеры представлены в документации.
В руководствах часто игнорируют возможные ошибки, но это не наш случай, давайте изменим 0 на 1 в файле с тестами и Cypress автоматически "прогонит" наши тесты вновь.
Подведем итог. В данном разделе мы узнали:
- как посетить нужный веб-сайт для теста (cy.visit).
- как найти элемент на странице (cy.get).
- как посмотреть содержимое найденного элемента (assertions).
Больше тестов, стабильней результат
Капитан Очевидность поработал над заголовком, а мы поработаем над новой партией тестов:
- убедимся, что по клику на "+" результат равен единице.
- убедимся, что по клику на "+" еще раз результат равен двум.
- убедимся, что по клику на "-" результат вновь равен единице (повторный клик на "минус" тестировать не будем).
Как я уже отмечал выше, Cypress позволяет не только найти элемент на странице, но также позволяет нам выполнить весь набор возможных действий (click, double click, right click, и т.д.). Нам потребуется click.
cypress/integration/main.js
Принцип тестов не изменился: сначала находим элемент с помощью cy.get, затем производим необходимые манипуляции.
Обратите внимание на порядок выполнения тестов. Сначала приложение загрузилось, затем мы кликнули на "плюс" - проверили, кликнули еще раз на "плюс" - проверили, кликнули на "минус" - проверили. Если мы в текущем коде поменяем it секции местами, то тесты могут сломаться. Так как мы тестируем последовательность действий, то наши тесты должны отрабатывать в корректной последовательности.
Итог раздела: научились эмулировать клики. Узнали, что порядок важен.
Новая фича: Reset (сброс результата)
Сначала напишем код, а затем напишем тест. Кое-кто воскликнет: "Постойте, а как же TDD?" На что мы ответим: спокойствие, end-to-end тесты можно (и я думаю даже нужно) писать после того, как код уже написан.
Добавляем кнопку (примеры кода на react, elm код здесь)
src/App.js
Добавляем тесты, но сначала план. Нам необходимо:
- убедиться, что у нас есть кнопка "Сбросить".
- кликнуть на кнопку.
- убедиться, что результат стал равен нулю.
В данном тестовом наборе у нас есть избыточный тест, в котором мы убеждаемся, что кнопка "Сбросить" отрисована. Так как в следующем тесте мы кликаем по данной кнопке и если кнопки не будет - Cypress сообщит нам об этом. Поэтому тест отрисовки кнопки "Сбросить" можно удалить.
На этом мы завершаем практическую часть. Исходный код приложения с тестами можно найти в соответствующей ветке (elm-репозиторий, react-репозиторий)
Какие минусы имеют end-to-end тесты?
Стабильность
По мнению многих, end-to-end тесты не стабильны. Сложно опровергать данное заявление, так как достичь 100% стабильности затруднительно. Однако, за многие годы Cypress добился достойных показателей по стабильности. Зачастую проблема не в том, что Cypress плох и не может выдать стабильный результат, а в том, что тест написан плохо и поэтому его результат не стабилен.
Посмотрите раздел документации Conditional Testing, почитайте советы.
Медлительность
Прогон end-to-end тестов занимает много времени. Тем не менее, это в разы быстрее чем ручное тестирование.
Конкуренты
Больше автоматизации
Любые тесты, в том числе и написанные на Cypress, приятнее запускать не в ручную, а в автоматическом режиме. На деле это выглядит так: у вас есть скрипт, который выпускает ваше приложение в свет. На одном из этапов у вас автоматически запускаются тесты, и если все в порядке - скрипт продолжает свою работу. Если вам интересно, почитайте материалы по CI/CD (например здесь).
Заключение
В данном материале мы узнали:
- что такое end-to-end тестирование и как оно может нам помочь.
- принцип тестирования: нашел элемент, выполнил действие, сравнил с ожиданием.
- какие существуют минусы.
Также на простых примерах мы попрактиковались в написании тестов.
Что дальше?
Посмотрите огромный тестовый набор от команды Cypress.
Посмотрите документацию.
Почитайте как тестировал свой продукт Саша Беспоясов.
Начните внедрять e2e тесты в вашей работе!
End-to-end тестирование не заменяет unit-тестов. Тестирование - это комплекс мер по поддержанию высокой планки качества, и e2e тесты лишь часть пирамиды тестирования.
Спасибо всем, кто дочитал до конца, а так же спасибо Selectel за мотивацию поработать "пером".
Если у вас остались вопросы - напишите в комментариях.