Разделы портала

Онлайн-тренинги

.
Руководство по использованию Cypress для перехвата API в UI-автоматизации
27.01.2025 00:00

Автор: Сватика Визань (Swathika Visagn)
Оригинал статьи
Перевод: Ольга Алифанова

Инженеры-автоматизаторы согласятся со мной: устойчивый фреймворк автоматизации – это солидный фундамент для проверки здоровья приложения. Задача добиться устойчивости, внедряя лучшие практики взаимодействия тестов с приложением – это и ответственность автоматизаторов, и их награда.

Одна из таких практик – это «перехватывать» API, что добавит очков зрелости тест-стратегии и фреймворку. Перехват означает взятие контроля над API путем подслушивания запросов и манипулирования ими через изменение свойств запроса или ответа. Я считаю, что это очень мощный инструмент автоматизаторов, помогающий создавать устойчивые тесты пограничных случаев.

В этой статье мы разберемся, что такое перехват API, и как успешно им воспользоваться, тестируя пользовательский интерфейс при помощи Cypress.

Что такое перехват API?

Термин «перехват» означает остановку и/или изменение чего-то до того, как оно достигнет цели. В тест-автоматизации перехват API означает захват собирающегося выстрелить API и манипуляцию его свойствами. Затем можно заглушить запрос, пока он не дошел до сервера, и схожим образом изменить свойства ответа, возвращенные сервером, до того, как они достигнут интерфейса. Это позволяет гибко манипулировать поведением интерфейса для проверки граничных случаев. Возможность перехвата API дают многие инструменты – из них наиболее популярны Cypress, Playwright и Postman.

Основная идея

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

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

Сшивание и перехват

Сшивание и перехват – два разных термина. Когда мы используем перехват API внутри UI-тестов, это называется «сшиванием». Мы подробно обсудили перехват, разберемся со сшиванием.

Если вдаваться в подробности, шов в швейном деле – это линия, по которой сшиваются два куска ткани. Сшивание в тест-автоматизации – это процесс соединения разных уровней тест-пирамиды. Энджи Джонс прекрасно объяснила это, как размывание границ тест-автоматизации, и продемонстрировала реальные примеры в своей статье. Ниже я продемонстрирую, как внедрить сшивание – то есть перехват API внутри UI-тестов – на реальном демо-приложении от Cypress.

Настройка и запуск демо-приложения

Для начала настройки приложения клонируйте RWA из официального GitHub-репозитория Cypress. Советую следовать пошаговым инструкциям на сайте Cypress до начала клонирования. Подсвечу самое важное:

Клонировав и запустив приложение, вы сможете успешно авторизоваться, используя список тестовых пользователей и паролей, предоставленный в разделе репозитория Getting Started. Если столкнетесь с проблемами, убедитесь, что ваша версия node совместима с приложением. Другие проблемы можно легко обсудить и решить при помощи сообщества Cypress.

Я запустил приложение, и появилась страница авторизации банка:


Изображение 1: Экран авторизации демо-приложения Cypress

Успешно авторизовавшись, вы попадете на домашнюю страницу:


Изображение 2: Домашняя страница демо-приложения Cypress

Настройка фреймворка Cypress

Запустив приложение, нужно построить фреймворк Cypress, чтобы создавать тесты. Для упрощения процесса рекомендую начать новый проект node.js, установив package.json и cypress. Так как эти шаги выходят за рамки статьи, предположу, что читатели знакомы с настройкой фреймворка Cypress с нуля – это довольно логичный процесс всего из трех команд.

Откройте новую директорию,

  • npm init для создания файла package.json
  • npm cypress install
  • npx cypress open

Взгляните сюда для настройки Cypress.

Обзор тест-сценариев

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

Тест-стратегии, о которых пойдет речь в этой статье:

  • Заглушка для тела ответа
  • Ожидание запроса и проверка свойств ответа (кода статуса)
  • Заглушка для кода статуса ответа
  • Заглушка для содержимого запроса.

Разберем эти стратегии подробно по порядку следования в списке.

Заглушка для тела ответа

Разберем тест-сценарии для заглушки тела ответа.

На вкладке личных операций для пользователя выводится ряд результатов. Перехватим API-запрос, возвращающий эти операции, и изменим тело ответа так, чтобы оно не возвращало результатов. Мне интересно, как UI справится с таким ответом, и какие изменения в нем произойдут.


Изображение 3: Страницы операций демо-приложения Cypress

В тестах Cypress следуйте этим шагам:

  • Шаг 1: Авторизация
  • Шаг 2: Перехват сетевого запроса, возвращающего транзакции, и заглушка ответа. Для получения этого API откройте средства разработчика и отслеживайте API-запросы на вкладке Network.
  • Шаг 3: На домашней странице кликните на вкладку ‘Mine’ [Отправится перехваченный API]
  • Шаг 4: Проверьте, что в интерфейсе нет ни одной транзакции, так как мы заглушили ответ пустыми результатами.

Исследуйте UI, чтобы увидеть, как API-запрос отправится при клике на вкладку ‘Mine’. Обращайте внимание на конечную точку URL, метод HTTP, наполнение (если есть), тело ответа и статус ответа.


Изображение 4: Детали API-запроса личных операций

У вкладки Network в инструментах разработчика есть вкладка Response, где можно видеть, что у тела есть свойство «результаты», содержащее все операции. Наша задача – заглушить ответ пустыми результатами.


Изображение 5: Детали API-запроса личных операций

Как можно видеть в тесте ниже, метод перехвата должен размещаться до конкретного действия пользователя (клика по вкладке Mine). Это позволит Cypress шпионить и прислушиваться к API-вызову. Как только по вкладке кликнули, Cypress заглушит результаты, заменив тело ответа с картинки выше на пустой объект. Я заглушаю ответ пустым телом JSON, синтаксис можно посмотреть в официальной документации Cypress. Когда выполнится тест ниже, вы увидите интерфейс с заглушенным ответом. Для валидации я проверяю, что локатор элемента UI для транзакций не существует.

describe("validate UI for no results in user transactions", () => {
it("should display a user friendly message for no results", () => {
   cy.loginApp();
   cy.intercept("/transactions", {
       body: {
         pageData: {
            page: 1,
            limit: 10,
            hasNextPages: true,
            totalPages: 24,
         },
         results: {},
      },
   }).as("personalTransactions");
   cy.get('[data-test="nav-personal-tab"]').click();
   cy.get('[data-test="transaction-item]').should("not.exist");
});
});

В Cypress runner на изображении ниже Cypress показывает перехваченный вызов API, используя алиас, ‘personalTransactions’. Из-за заглушки ответа в интерфейсе отсутствуют личные транзакции. Теперь я проверил, что локаторы для элементов транзакции не существуют на странице.


Изображение 6: Тест перехвата API личных транзакций

Ожидание запроса и проверка свойств ответа (кода статуса)

Иконка Notifications на домашней странице отображает все уведомления пользователя. В этом сценарии мы проверим, что код статуса ответа – 200.

В тестах Cypress следуйте шагам ниже:

  • Шаг 1: Авторизация
  • Шаг 2: Перехват сетевого запроса, получающего уведомления. Для получения этого API откройте средства разработчика и отслеживайте API-запросы на вкладке Network.
  • Шаг 3: Кликните по иконке ‘Notifications’ на домашней странице [Отправится перехваченный API]
  • Шаг 4: Проверьте интерфейс на основании ожидаемого или заглушенного ответа.

Исследуем UI, чтобы заглянуть в детали API. Конечная точка URL - /notifications, HTTP-метод – GET, а код статуса ответа для этого вызова должен быть 200.


Изображение 7: Детали API-запроса страницы уведомлений

Я перехватил этот URL и ожидал его, используя алиас. Проверку статуса ответа связана с возвращенным объектом. Синтаксис можно посмотреть тут.

describe("validate UI for user notifications", () => {
beforeEach("login the application", () => {
   cy.loginApp();
});
it("should return a status code of 200", () => {
cy.intercept("http://localhost:3001/notifications").as("notifications");
   cy.get('[data-test="nav-top-notifications-link"]').click();
cy.wait("@notifications").its("response.statusCode").should("eq", 200);
});
});

Cypress runner ниже показывает ожидание перехваченного алиаса и проверку, что код статуса ответа равен 200.


Изображение 8: Тест перехвата API уведомлений

Заглушка кода статуса ответа

В этом тест-сценарии мы будем использовать ту же вкладку Notifications, что и в предыдущем примере. Вместо проверки кода статуса ответа мы заглушим его, изменив на 401 (не авторизован), и проверим интерфейс для такого ответа.

В тестах Cypress следуйте шагам ниже:

  • Шаг 1: Авторизация
  • Шаг 2: Перехват запроса, получающего уведомления, и заглушка статуса ответа. Для получения этого API откройте средства разработчика и отслеживайте API-запросы на вкладке Network.
  • Шаг 3: Кликните по иконке ‘Notifications’ на домашней странице [Отправится перехваченный API]
  • Шаг 4: Проверьте интерфейс на соответствие заглушенному статусу ответа.

Синтаксис Cypress для заглушки кода статуса ответа можно посмотреть здесь. Заглушим статус ответа, заменив его на 401, и проверим, что UI-локатор для пустого списка уведомлений присутствует в DOM.

describe("validate UI for user notifications", () => {
beforeEach("login the application", () => {
   cy.loginApp();
});
it("should return a status code of 200", () => {
cy.intercept("http://localhost:3001/notifications").as("notifications");
   cy.get('[data-test="nav-top-notifications-link"]').click();
cy.wait("@notifications").its("response.statusCode").should("eq", 200);
});
it("stub response code to 401", () => {
   cy.intercept("GET", "/notifications", {
      statusCode: 401,
   }).as("notifications");
   cy.get('[data-test="nav-top-notifications-link"]').click();
cy.wait("@notifications").its("response.statusCode").should("eq", 401);
   cy.get('[data-test="empty-list-header"]').should("exist");
});
});

Cypress runner ниже демонстрирует, что код ответа заглушен, а список уведомлений пуст. Проверка присутствия UI-локатора для пустого списка прошла успешно.


Изображение 9: Уведомления в UI пусты из-за заглушенного API-ответа

Заглушка содержимого запроса

Это мой любимый сценарий – давайте посмотрим, о чем тут речь!

  • Как только Cypress загружает страницу авторизации, имя пользователя будет ‘Katharine.Bernier’.
  • Мы можем следить за API авторизации и изменить имя пользователя в теле исходящего запроса на ‘Jessyca.Kuhic’ до того, как запрос дойдет до сервера.
  • Когда после ввода данных происходит клик на кнопке Sign-In, перехваченный API авторизации изменит содержимое запроса, где находится имя пользователя 'Katharine.Bernier', на ‘Jessyca.Kuhic’ до того, как запрос дойдет до сервера.

Как упоминалось выше, список тестовых пользователей можно получить при помощи команды ниже, информация находится в секции Getting Started.

yarn list:dev:users

В интерфейсе вводится имя Katharina_Bernier.


Изображение 10: Авторизация в демо-приложении Cypress как Katharina_Bernier

После клика по SIGN IN вкладка Network показывает, что в запросе содержится имя пользователя Katharina_Bernier. Я меняю это тело запроса – имя пользователя изменится на Jessyca.Kuhic, существующего тестового пользователя, предоставленного Cypress.


Изображение 11: API авторизации, где указана Katharina_Bernier

Синтаксис отслеживания и изменения запроса с функцией routehandler можно найти здесь. Мы будем следить за вызовом API с конечной точкой /login. Когда такой запрос отправится, мы изменим его, поменяв имя пользователя на Jessyca.Kuhic – после отправки запроса мы проверим, что имя пользователя обновилось.

describe("validate user login", () => {
it("should modify the username in request payload", () => {
cy.visit("http://localhost:3000/");
cy.intercept("POST", "/login", (req) => {
req.body.username = "Jessyca.Kuhic";
}).as("interceptedLogin");
cy.get('[data-test="signin-username"]').type("Katharina_Bernier");
cy.get('[data-test="signin-password"]').type("s3cret");
cy.get('[data-test="signin-submit"]').click();
cy.wait("@interceptedLogin")
.its("request.body.username")
.should("eq", "Jessyca.Kuhic");
});
});

Cypress runner ниже демонстрирует, что пользователь авторизован как Katharina_Bernier, а перехваченный API показывает, что имя пользователя в запросе - Jessyca.Kuhic, и проверка прошла успешно. Это означает, что после авторизации в качестве Katharina_Bernier мы успешно заглушили содержимое запроса до того, как оно достигло сервера.

Примечание: в вашем проекте вы можете использовать аналогичный сценарий для заглушки содержимого невалидным пользователем, чтобы получить тело и статус ответа для неавторизованного пользователя.


Изображение 12: API авторизации с заменой содержимого на Jessyca.Kuhic

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

Я разместил свой репозиторий с тестами, о которых мы тут говорили, на GitHub. Это поможет вам сразу запустить тесты, запустив приложение. Пожалуйста, помните, что приложение должно быть запущено до запуска тестов Cypress.

Надеюсь, эта статья поможет вам внедрить сшивание в вашу тест-автоматизацию.

Заключение

Надеюсь, что мне удалось объяснить идею перехвата API и того, как это помогает улучшить ваши тесты. Я использую перехваты API в своих тестах, чтобы проверить результат взаимодействия с UI, сохранить свойство ответа в переменной окружения для использования в параметрах запросов, и для покрытия граничных сценариев, меняя свойства ответа. Другое важное преимущество перехватов – оно помогает управляться с хрупкостью UI. К примеру, я предпочитаю ожидать алиасов перехвата, а не жестко кодировать ожидания – как объясняется в этой статье.

Обсудить в форуме