Rest Assured и Postman – два подхода к тестированию API

Что такое API (Application Programming Interface) и зачем это тестировать? Если в двух словах, то API — это кусочки кода или правила, которые помогают сервисам интегрироваться друг с другом. API располагаются на серверах, что позволяет клиентам общаться с ними. API используются в службах и приложениях каждый день: при просмотре погоды или оплате картой онлайн. Важно регулярно тестировать API, поскольку они играют ключевую роль в разработке интеграций, а также в пользовательском опыте. 

В статье на примерах объясним, как выполнять request к API с помощью платформы Postman с заведением разных типов переменных с проверкой response. Также покажем реализацию автотестирования API с помощью популярной библиотеки Rest Assured. 

Postman поможет оперативно проверить endpoint в вашем тестируемым API, а Rest-Assured перенести автотесты в отдельный модуль в вашем проекте. Также, для старта работы в Postman, не требуется особых знаний языков программирования (потребуется при повышении автоматизации в тестовых проверках), Rest-Assured потребует основы знаний языка программирования.

Что такое API тестирование?

API позволяет упростить процесс создания приложения путем выделения классов и операций, которые необходимы при разработке. Чтобы приложения могли общаться между собой, следует их выполнить в едином архитектурном стиле – REST или SOAP. Тестирование API сводится к проверке бизнес-логики приложения, а также интеграционному тестированию, при выполнении которого можно выявить нестыковки в реализованной логике.

Коротко о методах запросов 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 ответа:

Ответы содержат следующие элементы:

  1. Версию HTTP-протокола (Version of the protocol)

  2. HTTP код состояния(код ответа), сообщающий об успешности запроса или причине неудачи (Status code)

  3. Сообщение состояния -- краткое описание кода состояния (Status message)

  4. HTTP заголовки, подобно заголовкам в запросах (Headers)

  5. Опционально: тело, содержащее пересылаемый ресурс

Заголовки 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 тестированию начните с определения тестовой стратегии, которая поможет вам описать проверки в ваших тест-кейсах при интеграционном и функциональном тестировании. 

А. При составлении тестовой стратегии необходимо познакомиться c Swagger или OpenAPI спецификациями для выполнения разных типов проверок:

  1. Проверка дублирования функциональности. Пример: вы создаете запись в справочнике с 2 разными endpoint)

  2. Проверка отсутствия функциональности. Пример: есть требование для выполнения CRUD (create, read, update, delete) операций в справочнике Users, но в спецификации отсутствует операция удаления записи).

  3. Проверка соответствия request и объекта данных. Пример: для создания пользователя в справочнике USERS необходимо направить UserDTO, но в спецификации указан неверный объект UserChangeDTO.

Б. После ознакомления со спецификацией следует определить целевые задачи для валидации конечного результата. Выделим основные шаги для контроля response для request к API:

  1. Выполнить проверки HTTP StatusCode (SC). Данный параметр позволит выявить на 1 этапе неправильную логику в работе API. Пример: при создании пользователя справочнике USERS в Response SC должен быть равен 201 Created, а не 500 Internal Server Error. Более подробно можно о возможных SC можно прочитать тут.

  2. Выполнить проверку response body. Пример: при создании пользователя в справочнике USERS в response возвращается json на основе UserDTO. Следует проверить соответствие между отправленными данными и возвращенными. Также для json возможно применить контроль по json-schema.

  3. Выполните оценку времени выполнения операции. Пример: если для вывода всех пользователей справочника USERS требуется 1 секунда, но фактический результат 50 секунд.

Тестирование в Postman

Создание запроса

При тестировании API, как правило, приходится выполнять CRUD (аббревиатура от операций create, read, update, delete операции). 

Создадим GET запрос для вычитки списка пользователей на странице 1. Для этого создадим коллекцию (папку в разделе Collection с запросами) с GET запросом. Для этого скачайте Postman. Далее выполните следующие действия:

  1. Создайте коллекцию с запросами. Для этого нажмите “New”. Далее в появившемся окне выберите “Collection” (по умолчанию имя новой коллекции New Collection).

  2. Нажмите ПКМ на имя коллекции, далее выбираем операцию “Add Request”.

  3. Выберите тип метода GET.

  4. Укажите URL = https://reqres.in/

  5. Перейдите во вкладку Params. Добавляем параметр Query Params с key=page, value=1.

  6. Сохраните запрос. Нажмите “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 поддерживает следующие типы переменных:

  1. Global позволяет вам получить доступ к данным между коллекциями, запросами, тестовыми сценариями и средами. Глобальные переменные доступны по всему рабочему пространству.

  2. Collection переменные коллекции, которые доступны всем запросам в коллекции, не зависит от переменных описанных в средах (environment).

  3. Environment переменные адаптированы для разветвления рабочих окружений (локальные, интеграционно-функциональные, препрод, прод).

  4. Data переменные поступают от внешних файлов CSV и JSON для определения наборов данных, которые вы можете использовать при запуске коллекций через Runner.

  5. Local переменные являются доступны только в скриптах вашего запроса.

Создадим коллекцию переменных окружения с переменной url. Для этого выполните следующие шаги:

  1. Выберите раздел “Environments”

  2. Нажмите “New”. Далее в появившемся окне выберите “Environments” (по умолчанию имя новой коллекции  New Environment)

  3. В поле variable введите имя переменной = url, type = default, initial value = https://reqres.in, current value = https://reqres.in

  4. Сохраните коллекцию с переменными

  5. Включите коллекцию с переменными

  6. Перейдите к ранее созданному запросу с методом GET. Измените URL запроса вместо https://reqres.in/api/users?page=1 введите {{url}}/api/users?page=1

  7. Нажмите “Send” для отправки запроса.

Дополнительно об переменных можно прочитать тут.

Создание тестов в запросе Postman

Выберите запрос, созданный ранее. Перейдите в вкладку Tests.

Создадим следующие проверки в response:

  1. Проверка status code = 200

pm.test("response status code is ok", function(){
pm.response.to.be.ok;
})
  1. Проверка что в Content Type have body

pm.test("response to be body", function(){
pm.response.to.be.withBody;
})
  1. Проверка, что в response нет строки ‘error’

pm.test("response to not have error", function(){
pm.response.to.not.have.jsonBody("error");
})
  1. Проверка, что в 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.0modelVersion>

  com.testit.rest.assuredgroupId>
  rest-assuredartifactId>
  1.0-SNAPSHOTversion>
  jarpackaging>

  rest-assured-samplename>
  http://maven.apache.orgurl>

 
    UTF-8project.build.sourceEncoding>
    UTF-8project.reporting.outputEncoding>
    1.7.0junit.platform.version>
    5.7.0junit.jupiter.version>
    4.2.0restAssured.version>
    2.22.2maven-surefire-plugin.version>
    3.8.1maven-compiler-plugin.version>
  properties>

 
   
      org.junit.platformgroupId>
      junit-platform-launcherartifactId>
      ${junit.platform.version}version>
    dependency>
   
      org.junit.jupitergroupId>
      junit-jupiterartifactId>
      ${junit.jupiter.version}version>
    dependency>
   
      io.rest-assuredgroupId>
      rest-assuredartifactId>
      ${restAssured.version}version>
    dependency>
  dependencies>

 
    installdefaultGoal>
   
     
        org.apache.maven.pluginsgroupId>
        maven-compiler-pluginartifactId>
        ${maven-compiler-plugin.version}version>
       
          UTF-8encoding>
          1.8source>
          1.8target>
        configuration>
      plugin>
     
        maven-surefire-pluginartifactId>
       
          truetestFailureIgnore>
        configuration>
        org.apache.maven.pluginsgroupId>
        ${maven-surefire-plugin.version}version>
      plugin>
    plugins>
  build>

project>


  • Создайте структуру папок

├───src

│   └───test

│       ├───java

│       │   └───com

│       │       ├───apiTests

│       │       ├───model

│       │       └───specification

│       └───resources

RequestSpecification и ResponseSpecification

Для выполнения принципа DRY (don’t repeat yourself) для определения спецификация запроса и ответа следует использовать при использовании Rest assured требуется описать 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:


Автор: Андрей Терёшин