REST Assured и Postman — два подхода к тестированию API
В статье на примерах объясним, как выполнять request к API с помощью платформы Postman с заведением разных типов переменных с проверкой response. Также покажем реализацию автотестирования API с помощью популярной библиотеки REST Assured.
Что такое API и зачем его тестировать
Если в двух словах, API (Application Programming Interface) — это кусочки кода или правила, которые помогают сервисам интегрироваться друг с другом. API располагаются на серверах, что позволяет клиентам общаться с ними. Используются в службах и приложениях каждый день: при просмотре погоды или оплате картой онлайн. Важно регулярно тестировать API, поскольку они играют ключевую роль в разработке интеграций, а также в пользовательском опыте.
API позволяет упростить процесс создания приложения путем выделения классов и операций, которые необходимы при разработке. Чтобы приложения могли общаться между собой, следует их выполнить в едином архитектурном стиле — REST или SOAP. Тестирование API сводится к проверке бизнес-логики приложения, а также интеграционному тестированию, при выполнении которого можно выявить нестыковки в реализованной логике.
Платформа Postman поможет оперативно проверить endpoint в вашем тестируемом API, а REST Assured — перенести автотесты в отдельный модуль в вашем проекте. Для старта работы в Postman не требуется знаний языков программирования (потребуется при повышении автоматизации в тестовых проверках), а REST Assured потребует основы знаний языка программирования.
Коротко о методах запросов HTTP
В http протоколе могут быть использованы следующие методы:
Наименование метода |
Описание |
GET |
Метод GET запрашивает представление ресурса. Запросы с использованием этого метода могут только извлекать данные |
HEAD |
HEAD запрашивает ресурс так же, как и метод GET, но без тела ответа |
POST |
POST используется для отправки сущностей к определённому ресурсу. Часто вызывает изменение состояния или какие-то побочные эффекты на сервере |
PUT |
PUT заменяет все текущие представления ресурса данными запроса |
DELETE |
DELETE удаляет указанный ресурс |
CONNECT |
CONNECT устанавливает «туннель» к серверу, определенному по ресурсу |
OPTIONS |
OPTIONS используется для описания параметров соединения с ресурсом |
TRACE |
TRACE выполняет вызов возвращаемого тестового сообщения с ресурса |
PATCH |
PATCH используется для частичного изменения ресурса |
Пример http запроса
Запросы содержат следующие элементы:
1. HTTP-метод (Method)
2. Путь (Path) к ресурсу: URL ресурсы лишены элементов, которые очевидны из контекста, например без protocol (http://), domain (здесь developer.mozilla.org), или TCP port (здесь 80).
3. Версию HTTP-протокола (Version of the protocol).
4. Заголовки (опционально), предоставляющие дополнительную информацию для сервера (Headers) или тело(body), для некоторых методов, таких как POST, которое содержит отправленный ресурс.
Пример http ответа
Ответы содержат следующие элементы:
-
Версию HTTP-протокола (Version of the protocol)
-
HTTP код состояния(код ответа), сообщающий об успешности запроса или причине неудачи (Status code)
-
Сообщение состояния — краткое описание кода состояния (Status message)
-
HTTP заголовки, подобно заголовкам в запросах (Headers)
-
Опционально: тело, содержащее пересылаемый ресурс
Заголовки HTTP позволяют клиенту и серверу отправлять дополнительную информацию с HTTP запросом или ответом. Таблица с детальным описанием headers представлена в статьях тут и тут.
Код ответа (код состояния, status code) — это элемент ответа HTTP сервера, который представляет собой три цифры. Первая цифра показывает, к какому классу состояния относится тот или иной код состояния (1хх, 2хх, 3хх, 4хх, 5хх). В HTTP насчитывают всего пять классов кодов состояний. HTTP коды состояний расширяемы, любой разработчик сервера может добавлять свои коды. Каждый код состояния тесно связан с HTTP методами: если метод — это элемент HTTP запроса, то код состояния — это HTTP ответ сервера, который означает то, как сервер понял запрос.
Группировка кодов ответов:
1. Информационные 100 – 199
2. Успешные 200 – 299
3. Перенаправления 300 – 399
4. Клиентские ошибки 400 – 499
5. Серверные ошибки 500 – 599
Подробнее читайте в статье по ссылке.
С чего начать тестирование API
При подготовке к API тестированию начните с определения тестовой стратегии, которая поможет вам описать проверки в ваших тест-кейсах при интеграционном и функциональном тестировании.
А. При составлении тестовой стратегии необходимо познакомиться cо Swagger или OpenAPI спецификациями для выполнения разных типов проверок:
-
Проверка дублирования функциональности
Пример: вы создаете запись в справочнике с двумя разными endpoint) -
Проверка отсутствия функциональности
Пример: есть требование для выполнения CRUD (create, read, update, delete) операций в справочнике Users, но в спецификации отсутствует операция удаления записи). -
Проверка соответствия request и объекта данных
Пример: для создания пользователя в справочнике USERS необходимо направить UserDTO, но в спецификации указан неверный объект UserChangeDTO.
Б. После ознакомления со спецификацией следует определить целевые задачи для валидации конечного результата. Выделим основные шаги для контроля response для request к API:
-
Выполнить проверки HTTP StatusCode (SC). Данный параметр позволит выявить на 1 этапе неправильную логику в работе API
Пример: при создании пользователя справочнике USERS в Response SC должен быть равен 201 Created, а не 500 Internal Server Error. Более подробно можно о возможных SC можно прочитать тут. -
Выполнить проверку response body
Пример: при создании пользователя в справочнике USERS в response возвращается json на основе UserDTO. Следует проверить соответствие между отправленными данными и возвращенными. Также для json возможно применить контроль по json-schema. -
Выполните оценку времени выполнения операции
Пример: если для вывода всех пользователей справочника USERS требуется 1 секунда, но фактический результат 50 секунд.
Тестирование в Postman
Создание запроса
При тестировании API, как правило, приходится выполнять CRUD (аббревиатура от операций create, read, update, delete операции).
Создадим GET запрос для вычитки списка пользователей на странице 1. Для этого создадим коллекцию (папку в разделе Collection с запросами) с GET запросом. Для этого скачайте Postman. Далее выполните следующие действия:
-
Создайте коллекцию с запросами. Для этого нажмите New. Далее в появившемся окне выберите Collection (по умолчанию имя новой коллекции New Collection).
-
Нажмите ПКМ на имя коллекции, далее выбираем операцию Add Request.
-
Выберите тип метода GET.
-
Укажите URL = https://reqres.in/
-
Перейдите во вкладку Params. Добавляем параметр Query Params с key=page, value=1.
-
Сохраните запрос. Нажмите Send, чтобы отправить запрос.
В ответе вы увидите список пользователей на странице 1 (https://reqres.in/api/users?page=1) справочника USERS с status code=200, status message=OK, время выполнения запроса 177ms, response size 1.85 KB
Примечание! Если запрос не был выполнен, проверьте, что у вас:
-
есть связь с сервером;
-
отключен ssl;
-
во вкладке Authorization не выбран Type (Type = No Auth).
Параметризация окружения
Postman поддерживает следующие типы переменных:
-
Global. Позволяет получить доступ к данным между коллекциями, запросами, тестовыми сценариями и средами. Глобальные переменные доступны по всему рабочему пространству.
-
Collection. Переменные коллекции, которые доступны всем запросам в коллекции, не зависят от переменных, описанных в средах (environment).
-
Environment. Переменные адаптированы для разветвления рабочих окружений (локальные, интеграционно-функциональные, препрод, прод).
-
Data. Поступают от внешних файлов CSV и JSON для определения наборов данных, которые вы можете использовать при запуске коллекций через Runner.
-
Local. Доступны только в скриптах вашего запроса.
Создадим коллекцию переменных окружения с переменной url. Для этого выполните следующие шаги:
-
Выберите раздел Environments
-
Нажмите New. Далее в появившемся окне выберите Environments (по умолчанию имя новой коллекции New Environment)
-
В поле variable введите имя переменной = url, type = default, initial value = https://reqres.in, current value = https://reqres.in
-
Сохраните коллекцию с переменными
-
Включите коллекцию с переменными
-
Перейдите к ранее созданному запросу с методом GET. Измените URL запроса: вместо https://reqres.in/api/users?page=1 введите {{url}}/api/users?page=1
-
Нажмите Send для отправки запроса.
Дополнительно о переменных читайте в статье по ссылке.
Создание тестов в запросе Postman
Выберите запрос, созданный ранее. Перейдите в вкладку Tests.
Создадим следующие проверки в response:
-
Проверка status code = 200
pm.test("response status code is ok", function(){ pm.response.to.be.ok; })
-
Проверка, что в Content Type have body
pm.test("response to be body", function(){ pm.response.to.be.withBody; })
-
Проверка, что в response нет строки ‘error’
pm.test("response to not have error", function(){ pm.response.to.not.have.jsonBody("error"); })
-
Проверка, что в response есть поле ‘page’ с value 1
pm.test("reponse object is contained 'page': 1", () => { const expectedObject = { "page": 1 }; pm.expect(pm.response.json()).to.deep.include(expectedObject); });
Выполните запрос. Перейдите в вкладку Test Results для проверки результатов тестов, которые мы написали.
Более подробно по скриптам проверок можно прочитать тут.
Пример автоматизированного тестирования с помощью библиотеки REST Assured
Библиотека REST Assured помогает выполнять тестирование REST-сервисов. Тесты, написанные с помощью данной библиотеки, пишутся на Java. Данная библиотека стала популярной благодаря простоте и удобной функциональности. Перейдем к практике.
Создание проекта
- Создайте проект с пакетным менеджером maven в intellij idea
- Вставьте следующие зависимости в pom файл
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.testit.rest.assured rest-assured 1.0-SNAPSHOT jar rest-assured-sample http://maven.apache.org UTF-8 UTF-8 1.7.0 5.7.0 4.2.0 2.22.2 3.8.1 org.junit.platform junit-platform-launcher ${junit.platform.version} org.junit.jupiter junit-jupiter ${junit.jupiter.version} io.rest-assured rest-assured ${restAssured.version} install org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} UTF-8
- Создайте структуру папок
├───src
│ └───test
│ ├───java
│ │ └───com
│ │ ├───apiTests
│ │ ├───model
│ │ └───specification
│ └───resources
RequestSpecification и ResponseSpecification
Для выполнения принципа DRY (don’t repeat yourself) при определении спецификации запроса и ответа требуется описать RequestSpecification и ResponseSpecification. Использование данных спецификаций позволит описать единожды поля, по которым будет выполняться запрос (RequestSpecification) или валидироваться ответ (ResponseSpecification).
- Создайте класс Specifications в каталоге src/test/java/com/specification
- Создайте RequestSpecification и ResponseSpecification
public class Specifications { public static RequestSpecification requestSpecification() { return new RequestSpecBuilder() .setBaseUri("https://reqres.in/")//---> Cтартовая URL .setRelaxedHTTPSValidation()//---> Отключение проверки сертификата .setContentType(JSON)//---> Установка Content Type .setAccept(JSON)//---> Установка Accept .build(); } public static ResponseSpecification responseSpecificationScOk() { return new ResponseSpecBuilder() .log(LogDetail.STATUS)//---> Уровень логирования .expectContentType(JSON)//---> Ожидаемый Content Type .expectStatusCode(HttpStatus.SC_OK)//---> Ожидаемый Status Code .expectResponseTime(lessThanOrEqualTo(3L), SECONDS)//---> Ожидаемое время ответа максимум 3 секунды .build(); }
Создание модели (DTO)
Создадим класс UserDTO с моделью (DTO) для выполнения запросов GET, POST, PUT, DELETE в каталоге src/test/java/com/model
public class UserDTO { public String name; public String job; public UserDTO(String name, String job) { this.name = name; this.job = job; } }
Написание автотестов
Будем писать автотесты для сайта https://reqres.in для запросов GET, POST, PUT, DELETE с разным способом валидации Response.
Тесты с запросом GET
- Тестирование запроса Get c проверкой status code = 200
- Тестирование запроса Get c проверкой key/value по полям id, email, first_name, last_name
- Тестирование запроса Get c валидацией ответа по json схеме
Создайте класс GetRequestTest в каталоге src/test/java/com/apiTests. Опишите тесты:
public class GetRequestTest { @Test @DisplayName("Тестирование запроса Get c проверкой status code = 200") public void getRequestCheckStatusCode() { RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .get("/api/users/2")//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_OK);//---> Проверка статус код } @Test @DisplayName("Тестирование запроса Get c проверкой key/value по полям id, email, first_name, last_name") public void getRequestCheckResponseJsonBody() { RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .get("/api/users/2")//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_OK)//---> Проверка статус код .assertThat() .body("data.id", Matchers.is(2))//---> Проверка Body по key и value в json .body("data.email", Matchers.is("janet.weaver@reqres.in"))//---> Проверка Body по key и value в json .body("data.first_name", Matchers.is("Janet"))//---> Проверка Body по key и value в json .body("data.last_name", Matchers.is("Weaver"));//---> Проверка Body по key и value в json } @Test @DisplayName("Тестирование запроса Get c валидацией ответа по json схеме") public void getRequestCheckResponseWithJsonSchema() { RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .get("/api/users/2")//---> Endpoint для выполнения запроса GET .then() .spec(responseSpecificationScOk())//---> Указание ResponseSpecification .assertThat() .body(matchesJsonSchemaInClasspath("SchemaUsersById.json"));//---> Валидация Response json по Json Schema. Сгенерировать Json Schema можно https://www.liquid-technologies.com/online-json-to-schema-converter и далее создать файл SchemaUsersById.json в каталоге src/test/resources. !!!Внимание по умолчанию вычитывается из папки resources помеченной как ресурсы тестов в проекте
} }
Тесты с запросом POST
- Тестирование тестового запроса Post с проверкой status code = 201
- Тестирование тестового запроса Post c проверкой key/value по полям name, job
Создайте класс PostRequestTest в каталоге src/test/java/com/apiTests. Опишите тесты:
public class PostRequestTest { @Test @DisplayName("Тестирование тестового запроса Post с проверкой status code = 201") public void postRequestCheckStatusCode() { RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .body(new UserDTO("morpheus", "leader"))//---> body для запроса с методом POST .post("/api/users")//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_CREATED);//---> Проверка статус код } @Test @DisplayName("Тестирование тестового запроса Post c проверкой key/value по полям name, job") public void postRequestCheckResponseJsonBody() { RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .body(new UserDTO("morpheus", "leader"))//---> body для запроса с методом POST .post("/api/users")//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_CREATED)//---> Проверка статус код .assertThat() .body("name", Matchers.is("morpheus"))//---> Проверка Body по key и value в json .body("job", Matchers.is("leader"));//---> Проверка Body по key и value в json } }
Тесты с запросом PUT
- Тестирование тестового запроса Put c обновлением данных Users по полю job
Создайте класс PutRequestTestкаталог src/test/java/com/apiTests. Опишите тесты:
public class PutRequestTest { @Test @DisplayName("Тестирование тестового запроса Put c обновлением данных Users по полю job") public void putRequestCheckStatusCodeAndJsonBody() { String id; id = RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .body(new UserDTO("morpheus", "leader"))//---> body для запроса с методом POST .post("/api/users")//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_CREATED)//---> Проверка статус код .assertThat() .body("name", Matchers.is("morpheus"))//---> Проверка Body по key и value в json .body("job", Matchers.is("leader"))//---> Проверка Body по key и value в json .extract() .response() .body() .path("id");//---> указания поля из Response Json для извлечения данных RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .body(new UserDTO("morpheus", "test_it"))//---> body с обновленными данными для запроса с методом PUT .post("/api/users" + id)//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_CREATED)//---> Проверка статус код .assertThat() .body("name", Matchers.is("morpheus"))//---> Проверка Body по key и value в json .body("job", Matchers.is("test_it"));//---> Проверка Body по key и value в json } }
Тесты с запросом DELETE
- Тестирование запроса Delete c удалением пользователя
Создайте класс DeleteRequestTest в каталоге src/test/java/com/apiTests. Опишите тесты:
public class DeleteRequestTest { @Test @DisplayName("Тестирование запроса Delete c удалением пользователя") public void deleteRequestCheckStatusCode() { int id;//---> Преобразование с int можно выполнять либо извлекать из Response значение id в виде строки id = Integer.parseInt(RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .body(new UserDTO("morpheus", "leader"))//---> body для запроса с методом POST .post("/api/users")//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_CREATED)//---> Проверка статус код .extract() .response() .body() .path("id"));//---> указания поля из Response Json для извлечения данных RestAssured.given() .spec(requestSpecification())//---> Указание RequestSpecification для формирования request .delete("/api/users/" + id)//---> Endpoint для выполнения запроса GET .then() .statusCode(HttpStatus.SC_NO_CONTENT);//---> Проверка статус код } }
Запуск тестов
Проверить работу описанных тестов можно в терминале IDE с помощью команды mvn clean test или с помощью junit.
Результат выполнения тестов с помощью maven:
Не пропустите Yoonion Big Meetup — уникальную бизнес-конференцию для топов и тимлидов из IT. Количество мест ограничено!