Тестирование API в Playwright/Java. GET-запросы

Начало работы 

Подробности о предварительных требованиях, установке и настройке уже обсуждались в предыдущих частях туториала

Тестируемое приложение 

Продолжаем работать с бесплатными тестовыми API restful-ecommerce демо-приложения магазина, проект выложен на GitHub. Проект может быть установлен локально с помощью node или docker. В нем созданы несколько API, связанных с управлением заказами — создание, обновление, получение и удаление заказов. 

Напомним, что такое GET-запрос

GET-запрос извлекает данные из указанного источника. Это наиболее часто используемый метод HTTP. Он не требует отправки тела запроса для получения данных из источника, однако в качестве заголовка могут потребоваться параметры для фильтрации, называемые Query Params и Path Params, чтобы отфильтровать и получить запись в нужном виде. 

Запрос GET стандартно возвращает статус-код 200вместе с запрошенными данными. В зависимости от Content-Type данные могут быть получены в формате JSON или XML. 

В следующем примере restful-ecommerce API есть 2 эндпойнта (далее конечные точки) API, которые мы сейчас будем тестировать.

  1. Конечная точка GET /getAllOrders — Получает все доступные заказы в системе

Этот API возвращает в ответ статус-код 200, с данными о заказе в формате JSON.

Если такие заказы не найдены, возвращается код состояния 404, с сообщением «Заказ не найден !!!» 

2. Конечная точка GET /getOrder — Получение заказа с фильтром либо по id заказа, либо по id пользователя, либо по id продукта, либо по всем этим параметрам.

GET-запрос вернет код состояния 200 с отфильтрованным заказом в ответе, в противном случае вернет код состояния 404 с сообщением «No order found with the given parameter«.

Приступим.

Сценарий тестирования 1 — Получение всех заказов 

  1. Запускаем сервис для приложения restful-ecommerce
  2. Запускаем конечную точку GET /getAllOrders, чтобы получить все доступные заказы в системе 
  3. Проверяем, что в ответ получен код состояния 200 
  4. Проверяем, что в ответ получены правильные данные

Примечание: Ранее мы уже создавали 4 заказа с помощью POST-запроса. Мы будем использовать получение тех же данных о заказах с помощью конечной точки GET /getAllOrders

Реализация теста 

Создадим новый тестовый метод testShouldGetAllOrders() в существующем тестовом классе HappyPathTests

Просто повторяю, что в части туториала по POST-запросам было создано два тестовых класса, HappyPathTests и SadPathTests, также был добавлен класс BaseTest для конфигурирования и настройки Playwright.

    @Test
    public void testShouldGetAllOrders() {

        final APIResponse response = this.request.get("/getAllOrders");

        final JSONObject responseObject = new JSONObject(response.text());
        final JSONArray ordersArray = responseObject.getJSONArray("orders");

        assertEquals(response.status(), 200);
        assertEquals(responseObject.get("message"), "Orders fetched successfully!");
        assertEquals(this.orderList.get(0).getUserId(), ordersArray.getJSONObject(0).get("user_id"));
        assertEquals(this.orderList.get(0).getProductId(), ordersArray.getJSONObject(0).get("product_id"));
        assertEquals(this.orderList.get(0).getTotalAmt(), ordersArray.getJSONObject(0).get("total_amt"));
    }

Результат запроса к API будет сохранен в переменной response, которая определена для типа APIResponse. GET-запрос будет отправлен с помощью this.request.get("/getAllOrders"), который обработает GET-запрос и получит данные из системы.

Ответ будет получен с помощью метода response.text() Playwright и сохранен в переменной responseObject, имеющей тип JSONObject (это класс библиотеки org.json). Ниже приведен ответ, полученный в формате JSON для конечной точки GET /getAllOrders.

{
  "message": "Orders fetched successfully!",
  "orders": [
    {
      "id": 1,
      "user_id": "3",
      "product_id": "331",
      "product_name": "Aerodynamic Cotton Bench",
      "product_amount": 416,
      "qty": 4,
      "tax_amt": 47,
      "total_amt": 1711
    },
    {
      "id": 2,
      "user_id": "2",
      "product_id": "331",
      "product_name": "Incredible Linen Keyboard",
      "product_amount": 716,
      "qty": 1,
      "tax_amt": 45,
      "total_amt": 761
    },
    {
      "id": 3,
      "user_id": "2",
      "product_id": "332",
      "product_name": "Gorgeous Concrete Bench",
      "product_amount": 900,
      "qty": 2,
      "tax_amt": 38,
      "total_amt": 1838
    },
    {
      "id": 4,
      "user_id": "2",
      "product_id": "331",
      "product_name": "Ergonomic Concrete Gloves",
      "product_amount": 584,
      "qty": 2,
      "tax_amt": 21,
      "total_amt": 1189
    }
  ]
}

Поскольку внешняя часть ответа представляет собой JSON-объект, значения сохраняются с помощью класса JSONObject.

final JSONObject responseObject = new JSONObject(response.text());

Однако данные о заказе подтягиваются в виде массива JSON, поэтому данные о заказе хранятся в переменной ordersArray.

final JSONArray ordersArray = responseObject.getJSONArray("orders");

Наконец, будут выполнены ассерты, проверяющие, что GET /getAllOrders возвращает статус-код 200. Метод response.status() вернет статус-код. 

Переменная responseObject хранит полученный ответ, поэтому мы получим поле message из этого JSON-объекта, чтобы проверить, что оно содержит текст «Orders fetched successfully!«

В предыдущей части туториала мы использовали класс OrderData для генерации данных о заказах с помощью DataFaker и Lombok, а в тестах POST-запроса мы объявили List<OrderData> с переменной orderList. Этот же объект будет вызываться в ассерте для проверки целостности полученных данных о заказе. Ниже приведен JSON-массив, который извлекается в ответ.

"orders": [
    {
      "id": 1,
      "user_id": "3",
      "product_id": "331",
      "product_name": "Aerodynamic Cotton Bench",
      "product_amount": 416,
      "qty": 4,
      "tax_amt": 47,
      "total_amt": 1711
    },
    {
      "id": 2,
      "user_id": "2",
      "product_id": "331",
      "product_name": "Incredible Linen Keyboard",
      "product_amount": 716,
      "qty": 1,
      "tax_amt": 45,
      "total_amt": 761
    },
    {
      "id": 3,
      "user_id": "2",
      "product_id": "332",
      "product_name": "Gorgeous Concrete Bench",
      "product_amount": 900,
      "qty": 2,
      "tax_amt": 38,
      "total_amt": 1838
    },
    {
      "id": 4,
      "user_id": "2",
      "product_id": "331",
      "product_name": "Ergonomic Concrete Gloves",
      "product_amount": 584,
      "qty": 2,
      "tax_amt": 21,
      "total_amt": 1189
    }
  ]

Мы будем проверять первый объект из массива order.

{
      "id": 1,
      "user_id": "3",
      "product_id": "331",
      "product_name": "Aerodynamic Cotton Bench",
      "product_amount": 416,
      "qty": 4,
      "tax_amt": 47,
      "total_amt": 1711
 }

Следующие строки кода получат из объекта значения user_id, product_id и total_amt и, соответственно, используют данные, которые были переданы с помощью переменной orderList (данные генерируются во время выполнения с помощью Datafaker и Lombok).

assertEquals(this.orderList.get(0).getUserId(), ordersArray.getJSONObject(0).get("user_id"));
assertEquals(this.orderList.get(0).getProductId(), ordersArray.getJSONObject(0).get("product_id"));
assertEquals(this.orderList.get(0).getTotalAmt(), ordersArray.getJSONObject(0).get("total_amt"));

Выполнение теста 

Сначала нам нужно убедиться, что приложение restful-ecommerce запущено и работает. Ознакомьтесь с шагами здесь, чтобы запустить приложение на вашей локальной машине. 

Мы будем выполнять POST-запрос (сгенерированный в соответствующей части туториала) и GET-запрос, используя файл testng.xml ниже. POST-запрос сгенерирует заказы, а GET-запрос получит заказы и выполнит необходимые ассерты.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Restful ECommerce Test Suite">
    <test name="Testing Happy Path Scenarios of Restful E-Commerce APIs">
        <classes>
            <class name="io.github.mfaisalkhatri.api.restfulecommerce.HappyPathTests">
                <methods>
                    <include name="testShouldCreateNewOrders"/>
                    <include name="testShouldGetAllOrders"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>

Скриншот из IntelliJ IDE показывает, что выполнение теста прошло успешно и заказы были получены успешно.

Сценарий тестирования 2 — Получение отфильтрованных заказов по order_id 

  1. Запустить службу для приложения restful-ecommerce 
  2. Запустить конечную точку GET /getOrder для получения фильтрации заказов по order_id с помощью параметра Query 
  3. Проверить, что в ответ получен код состояния 200 
  4. Проверить, что в ответ получены правильные данные

Реализация теста 

Создадим новый тестовый метод testShouldGetOrderUsingOrderId() и реализуем в нем тестовый сценарий 2.

@Test
public void testShouldGetOrderUsingOrderId() {
    final int orderId = 1;
    final APIResponse response = this.request.get("/getOrder", RequestOptions.create().setQueryParam("id", orderId));

    final JSONObject responseObject = new JSONObject(response.text());
    final JSONArray ordersArray = responseObject.getJSONArray("orders");

    assertEquals(response.status(), 200);
    assertEquals(ordersArray.getJSONObject(0).get("id"), orderId);
    assertEquals(responseObject.get("message"), "Order found!!");

}

У нас уже есть несколько заказов, созданных в системе. Мы будем получать заказ с order_id = 1 

Для получения заказа с фильтром order_id нам нужно указать order_id в качестве параметра запроса. Это можно сделать с помощью следующей строки:

Параметр запроса передается с помощью метода setQueryParam() из интерфейса RequestOptions в Playwright. В качестве параметра в метод setQueryParam() нужно передать имя параметра и его требуемое значение. 

Далее нам нужно обработать объект ответа и получить его в формате JSON. Метод response.text() возвращает ответ API в формате String. Эта строка будет преобразована в обработанный объект JSON с помощью класса JSONObject из библиотеки org.json.

Обработанный объект JSON будет в дальнейшем использоваться для выполнения ассертов. Здесь не будет проверок целостности данных, мы только проверяем, что объект ответа имеет тот же order_id, который мы указали в запросе, и в ответе возвращается статус-код 200

Далее мы проверяем, что поле message в ответе имеет текст «Заказ найден!!!» 

Выполнение теста 

Добавим этот метод в тот же файл testng.xml, перезапустим приложение restful-ecommerce, чтобы у нас было свежее приложение без данных, и запустим все тесты снова.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Restful ECommerce Test Suite">
    <test name="Testing Happy Path Scenarios of Restful E-Commerce APIs">
        <classes>
            <class name="io.github.mfaisalkhatri.api.restfulecommerce.HappyPathTests">
                <methods>
                    <include name="testShouldCreateNewOrders"/>
                    <include name="testShouldGetAllOrders"/>
                    <include name="testShouldGetOrderUsingOrderId"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>

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

Тестовый сценарий 3 — Получение фильтрации заказов по нескольким параметрам запроса 

  1. Запустить сервис для приложения restful-ecommerce 
  2. Запустить конечную точку GET /getOrder для получения фильтрации заказов по параметрам запроса order_id, product_id и user_id 
  3. Проверить, что в ответе получен код состояния 200 
  4. Проверить, что в ответе получены правильные данные

Реализация теста 

Реализация этого тестового сценария практически такая же, как и для тестового сценария 2. Единственным дополнением здесь будет добавление параметров запроса product_id и user_id в тестовый метод.

Новый тестовый метод testShouldGetOrdersUsingOrderIdProductIdAndUserId() добавляется в существующий класс HappyPathTests.

@Test
    public void testShouldGetOrdersUsingOrderIdProductIdAndUserId() {
        final int orderId = 2;
        final String productId = "332";
        final String userId = "2";


        final APIResponse response = this.request.get("/getOrder", RequestOptions.create()
                .setQueryParam("id", orderId)
                .setQueryParam("product_id", productId)
                .setQueryParam("user_id", userId));

        final JSONObject responseObject = new JSONObject(response.text());
        final JSONArray ordersArray = responseObject.getJSONArray("orders");

        assertEquals(response.status(), 200);
        assertEquals(responseObject.get("message"), "Order found!!");
        assertEquals(ordersArray.getJSONObject(0).get("id"), orderId);
        assertEquals(ordersArray.getJSONObject(0).get("product_id"), productId);
        assertEquals(ordersArray.getJSONObject(0).get("user_id"), userId);

    }

В этом тестовом методе setQueryParam вызывается три раза, чтобы передать необходимые параметры.

Остальная часть реализации, связанная с разбором ответа и проверкой статус-кода и сообщения, остается прежней. Кроме того, в метод добавлены ассерты, проверяющие, что полученная в ответе информация о заказе имеет заданные order_id, product_id и user_id. Этот ассерт гарантирует, что были получены правильные данные о заказе в соответствии с параметрами запроса.

Выполнение теста 

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

Резюме

Запросы GET позволяют получить необходимые данные с указанного ресурса. Это наиболее часто используемый метод HTTP. Обычно он возвращает данные в ответ с кодом состояния 200. GET-запросы также могут учитывать необходимые фильтры с помощью параметров запроса или параметров пути для запроса данных. 

При тестировании GET-запросов нам необходимо проверять правильность данных, полученных в ответе. Эта проверка будет проводиться для всех данных, получаемых сразу или в соответствии с заданными параметрами запроса.

Playwright предоставляет метод get() в интерфейсе APIRequestContext, который можно использовать для получения данных. Также поддерживаются определенные параметры запроса: заголовки, параметры запроса и т. д. 

M.S.Khatri

***

Какой была ваша первая зарплата в QA и как вы искали первую работу?

Мега обсуждение в нашем телеграм-канале о поиске первой работы. Обмен опытом и мнения.

Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

Мы в Telegram

Наш официальный канал
Полезные материалы и тесты
Готовимся к собеседованию
Project- и Product-менеджмент

? Популярное

? Telegram-обсуждения

Наши подписчики обсуждают, как искали первую работу в QA. Некоторые ищут ее прямо сейчас.
Наши подписчики рассказывают о том, как не бояться задавать тупые вопросы и чувствовать себя уверенно в новой команде.
Обсуждаем, куда лучше податься - в менеджмент или по технической ветке?
Говорим о конфликтных ситуациях в команде и о том, как их избежать
$1100*
медианная зарплата в QA в июне 2023

*по результатам опроса QA-инженеров в нашем телеграм-канале

Собеседование

19%*
IT-специалистов переехало или приняло решение о переезде из России по состоянию на конец марта 2022

*по результатам опроса в нашем телеграм-канале

live

Обсуждают сейчас