[Перевод] Как Cypress развивался в качестве инструмента автоматизации тестирования фронтенда в QuintoAndar

От хакатона 2 года назад до 20+ фронтенд-приложений, выполняющих интеграционные тесты с Cypress. Проблемы и решения, с которыми мы столкнулись при автоматизации тестирования интерфейсов на данный момент.

Почему Cypress

Cypress — это мощный инструмент автоматизации тестирования фронтенда, созданный для веба. Это более новая альтернатива Selenium, стандартному на рынке инструменту для тестирования интерфейсов.

Писать тесты для Cypress очень просто, а его способность тестировать фронтенд веб-приложений заставила нас создать PoC на нашем основном фронтенд-сервисе.

Проектные решения

С самого начала мы решили использовать PageObject для структурирования тестов. Это не то, что рекомендует Cypress, но для нас это хорошо сработало. Мы используем react, а с помощью объектов страниц на Cypress мы можем компоновать элементы на обеих сторонах, продукт и тест. Когда все организовано в компоненты и объекты страниц, можно повторно использовать их в разных тестах, и таким образом еще быстрее создавать новые тестовые сценарии.

Например: на странице обзора этого предложения есть таблица цен. Такая же таблица цен используется на нескольких других страницах. Поэтому в папке Cypress был создан тест класса под названием pricedTable.

6dcd5a2629be95478fc920e5e0c6e93a.png

class PricedTable {
  getCloseButton = () => cy.get('button[aria-label="Fechar"]');
  verifyRentPrice = (mock) => {
    const offer = getOfferMock(mock);
    cy.contains(`R$ ${offer.house.rentPrice}`);
  };
  verifyIPTUDialogText = () => {
     cy.contains(‘h2’, pricedTableMessages.IPTU);};
  }
}

Таким образом, мы можем легко переиспользовать команды таблицы на разных страницах.

Тесты на странице обзора предложения будут выглядеть следующим образом

before(() => {
  page = new OfferReviewPage();
  cy.setLoginCookies();
  page.visit(‘with-resident’);
});
it(‘should check rentPrice, titles and buttons rendered’, () ={
  page.verifyPageTitles();
  page.pricedTable.verifyRentPrice(‘with-resident’);
  page.getSubmitReviewPrimaryButton().should(‘be.enabled’);
  page.getSubmitReviewSecondaryButton().should(‘be.enabled’);
});
it(‘should open IPTU more info dialog’, () => {
  page.getIPTUInfoButton().click();
  page.pricedTable.verifyIPTUDialogText();
  page.pricedTable.getCloseButton().click();
});

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

Решение о создании моков с целью избежать нестабильности (flakiness)

Как только мы начали увеличивать охват интеграционных тестов на нашем основном PWA, мы столкнулись с самым большим кошмаром автоматизированных тестов — нестабильностю (flakiness). Тесты были нестабильны не только, но в основном потому, что бэкенд, который мы использовали, был нестабилен и часто не отвечал должным образом. Поскольку эти тесты должны использоваться как инструменты разработки, а не только как CI-проверки, мы решили иметь разные тест-сьюты End-to-End и интеграционных тестов и сделать тест-сьют интеграционных тестов устойчивым к нестабильности API разработки. Мы добились этого, используя две стратегии:

  1. Повторные запросы: мы добавили 3 повторных запроса по умолчанию в тест-сьют.

  2. Создание моков для наиболее нестабильных API: мы добавили тестовые моки на сетевой уровень, чтобы предотвращать ошибки на этапе интеграции. В контексте пользовательского интерфейса мы не фокусируемся на тестировании бэкенда, поэтому мы можем имитировать API без потери качества.

Метрики тестирования

С ростом использования Cypress во все большем количестве приложений мы почувствовали необходимость извлекать метрики из наших тестов. Мы решили сопоставить генерируемые Cypress отчеты с базой данных, где мы могли бы создавать дашборды.

График, показывающий продолжительность теста и количество неудач

График, показывающий продолжительность теста и количество неудач

После каждого запуска теста мы используем mochawesome для объединения всех json-файлов, созданных во время выполнения тестов, и генерируем html-отчет, содержащий скриншоты ошибок. Этот объединенный json-файл, содержащий всю информацию о выполнении теста, загружается на S3 вместе с html-отчетом и скриншотами ошибок. Оттуда у нас есть процесс обработки данных, который переносит json-файлы из S3 в базу данных. В этой базе данных мы можем проследить историю тестов и определить, слишком ли часто тесты терпят неудачу или какой-либо тест прошел после повторной попытки. На основе этих дашбордов мы можем выявить нестабильные тесты и работать над ними.

Диаграмма, показывающая ошибки в тестировании по дням в течение последней недели

Диаграмма, показывающая ошибки в тестировании по дням в течение последней недели

Создание вспомогательной платформы для UI-тестов

Когда мы выросли с 1 до 5 PWA, выполняющих интеграционные тесты с Cypress, мы все еще могли контролировать версии, хорошие практики и команды. Однако, когда мы начали расти до 10+ PWA, ситуация начала выходить из-под контроля. В этот момент мы решили создать единый репозиторий с пакетами, которые будут служить «тестовой платформой» для всех приложений. Был создан pwa-test-tools, в котором централизовано хранились версия Cypress, конфигурации размеров экрана, базовые команды, общие для всех PWA, как логин, отчеты и сам запуск Cypress. Таким образом, любое изменение в этом инструменте может быть легко использовано в любой команде внутри компании для любого PWA.

Доступность/Accessibility

Доступность фронтенда для людей с ограниченными возможностями становится все более важной задачей в QuintoAndar. Поскольку Cypress работает на 10+ PWA, мы заметили возможность проверить ошибки доступности во время выполнения и

нтеграционных тестов. Тогда мы начали использовать cypress-axe. Cypress axe использует правила доступности axe-core и проверяет, соблюдаются ли эти правила на html-странице во время выполнения Cypress. Автоматизированные тесты доступности обнаруживают 57,38% всех ошибок доступности. Это легко реализовать, и это гарантирует, что большинство основных ошибок доступности не дойдут до продакшена.

e2e тестирование

В течение последних нескольких месяцев мы работали над созданием фреймворков для использования Cypress в качестве сквозного (end-to-end) тестирования. Мы начали работать над определением основных сценариев, которые мы хотим автоматизировать. Из-за отсутствия подходящей среды для их запуска мы создали несколько тестов, используя продакшн-среду без создания каких-либо транзакционных данных. Затем мы связали эти сквозные тесты с Prometheus. Таким образом можно извлекать метрики и получать предупреждения, когда тест не проходит или не выполняется. В ближайшее время я напишу статью, посвященную сквозному тестированию с использованием Cypress.

Новые функции X новые тесты

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

Лучший способ упростить создание автоматизированных тестов — думать об этом с точки зрения дизайна страницы.

  • QA смотрит на дизайн страницы и определяет, какие тесты должны быть покрыты интеграционными тестами.

  • QA анализирует элементы, которые было бы трудно выбрать на Cypress. Эти элементы могут содержать data-testid. Способ легко найти элементы, но избегая при этом использования идентификаторов, так как они затрудняют работу с компонентами.

  • QA создает задачу интеграционного тестирования в рамках задачи по новой функции. Задача может содержать сценарии, которые будут покрыты в тест-кейсах.

  • Фронтенд-разработчик создает страницу, добавляя data-testid в нужные места.

  • QA или разработчик легко реализуют тесты, поскольку самые сложные элементы уже имеют data-testid.

Долгий путь

Чтобы пройти путь от Cypress PоC до сотен тест-кейсов, созданных для 20+ фронтенд-приложений, QuintoAndar потребовалось почти 2 года и много усилий. Мы продвигались всегда понемногу, ожидая столкновения с проблемами, чтобы затем искать лучшее решение. Нам еще предстоит пройти долгий путь, особенно если мы хотим, чтобы Cypress стал частью нашей культуры разработки.

А всех, кому актуален вопрос поиска работы и прохождения собеседований на позицию автоматизатора тестирования, приглашаем на открытое занятие, которое пройдет уже послезавтра в рамках курса «JavaScript QA Engineer».

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

© Habrahabr.ru