От хакатона 2 года назад до 20+ фронтенд-приложений, выполняющих интеграционные тесты с Cypress. Проблемы и решения, с которыми мы столкнулись при автоматизации тестирования интерфейсов на данный момент.
Почему Cypress
Cypress — это мощный инструмент автоматизации тестирования фронтенда, созданный для веба. Это более новая альтернатива Selenium, стандартному на рынке инструменту для тестирования интерфейсов.
Писать тесты для Cypress очень просто, а его способность тестировать фронтенд веб-приложений заставила нас создать PoC на нашем основном фронтенд-сервисе.
Проектные решения
С самого начала мы решили использовать PageObject для структурирования тестов. Это не то, что рекомендует Cypress, но для нас это хорошо сработало. Мы используем react, а с помощью объектов страниц на Cypress мы можем компоновать элементы на обеих сторонах, продукт и тест. Когда все организовано в компоненты и объекты страниц, можно повторно использовать их в разных тестах, и таким образом еще быстрее создавать новые тестовые сценарии.
Например: на странице обзора этого предложения есть таблица цен. Такая же таблица цен используется на нескольких других страницах. Поэтому в папке Cypress был создан тест класса под названием pricedTable.
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 разработки. Мы добились этого, используя две стратегии:
Повторные запросы: мы добавили 3 повторных запроса по умолчанию в тест-сьют.
Создание моков для наиболее нестабильных 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".
На этой встрече рассмотрим типичный процесс собеседования на позицию автоматизатора тестирования и поделимся лучшими практиками по его подготовке. Обсудим основные технические навыки, которые нужны для этой позиции, а также навыки коммуникации, презентации и работы в команде.