тестирование api с rest assured

Как проводить тестирование API с помощью REST Assured

API играет важную роль в развитии ПО. Поэтому правильное автоматизированное тестирование API становится всё более необходимым. Существует множество различных инструментов, которые помогут вам в написании автоматизированных тестов. Эта статья расскажет об использовании одного из самых популярных инструментов для этой задачи: REST Assured.

REST Assured — это библиотека Java, предназначенная для тестирования RESTful API. Вы также можете копировать и использовать примеры кода из этой статьи.

Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ

Начало работы: Конфигурация

Чтобы начать работу с REST Assured, просто внесите его в качестве зависимости в свой проект. Если вы используете Maven, добавьте следующую запись в ваш pom.xml:

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>3.0.2</version>
    <scope>test</scope>
</dependency>

И для Gradle:

testCompile 'io.rest-assured:rest-assured:3.0.2'

REST Assured можно использовать с фреймворками для модульного тестирования, такими как JUnit и TestNG. В примерах из этой статьи REST Assured использовался вместе с TestNG.

После настройки импорта REST Assured, добавьте следующие статические «импорты» в ваш тестовый класс:

import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

Первый тест: Понимание синтаксиса

В статье будет тестироваться API базы данных автогонок Ergast, который можно найти здесь. Этот API предоставляет данные, связанные с гонками Формулы-1, гонщиками, трассами и многим другим.

Ниже приведён тест, написанный с помощью REST Assured, который получает список трасс 2017 года в формате JSON и проверяет, есть ли в списке 20 трасс:

@Test
public void test_NumberOfCircuitsFor2017Season_ShouldBe20() {
        
    given().
    when().
        get("http://ergast.com/api/f1/2017/circuits.json").
    then().
        assertThat().
        body("MRData.CircuitTable.Circuits.circuitId",hasSize(20));
}

Обратите внимание, что API, используемый REST Assured, поддерживает синтаксис Given/When/Then. Благодаря чему тест легко читается и выполняет все необходимые действия всего в одной строке кода.

Матчер hasSize() в Hamcrest подсчитывает количество трасс — вот почему вам нужно было добавить Hamcrest в качестве статического импорта. Библиотека Hamcrest содержит набор матчеров, которые позволяют создавать верификации всех видов, сохраняя их читабельность.

В верификационной части теста выполняется следующее:

  • Запоминает (JSON) ответ на запрос API.
  • Запрашивает все элементы с именем circuitId, используя выражение Groovy GPath "MRData.CircuitTable.Circuits.circuitId".
  • Проверяет, что полученное количество элементов circuitId равно 20.

В Hamcrest существуют матчеры для большого количества различных проверок, включая equalTo() для равенства, lessThan() и greaterThan() для сравнения, hasItem() для проверки, содержит ли база данных запрашиваемый элемент, и многие другие. Полный список матчеров приведен в документации библиотеки Hamcrest.

Валидация данных ответа

С помощью REST Assured вы можете не только проверить содержимое тела ответа, но и проконтролировать его технические характеристики, такие как код состояния HTTP, формат содержимого ответа и т. д. В приведенном ниже примере проверяется следующее:

  • Код состояния ответа — 200.
  • Формат содержимого ответа (указывает получателю, как интерпретировать тело ответа) — "application/json".
  • Значение заголовка ответа "Content-Length" равно 4567.
@Test
public void test_ResponseHeaderData_ShouldBeCorrect() {
        
    given().
    when().
        get("http://ergast.com/api/f1/2017/circuits.json").
    then().
        assertThat().
        statusCode(200).
    and().
        contentType(ContentType.JSON).
    and().
        header("Content-Length",equalTo("4567"));
}

Этот пример также показывает, как легко объединить проверки в удобный и читаемый вид с помощью метода and(). Единственная функция этого метода — делать код более простым к восприятию.

Параметризованные тесты

Часто возникает необходимость проводить один и тот же тест с различными наборами данных. Вместо того чтобы писать новый тест для каждого набора, вы можете создать параметризованный тест (parameterized test). И передать ему столько тестовых данных, сколько требуется для успешного покрытия теста.

RESTful API поддерживают два различных типа параметров:

  • Параметры запроса (query parameters). Они добавляются в конце конечной точки RESTful API и их можно отличить по знаку вопроса перед ними. Например, в конечной точке http://md5.jsontest.com/?text=test “text” является параметром запроса (со значением “test”).
  • Параметры пути (path parameters). Они являются частью конечной точки RESTful API. Например, в конечной точке http://ergast.com/api/f1/2017/circuits.json, “2017” — это значение параметра пути. Попробуйте заменить его на “2016” и посмотрите, что произойдет (подсказка: тест должен провалиться, так как в 2016 году была 21 гонка Формулы-1, а не 20).

REST Assured может работать с обоими типами параметров. Сначала посмотрим, как можно задать и использовать параметр запроса из примера выше:

@Test
public void test_Md5CheckSumForTest_ShouldBe098f6bcd4621d373cade4e832627b4f6() {
    
    String originalText = "test";
    String expectedMd5CheckSum = "098f6bcd4621d373cade4e832627b4f6";
        
    given().
        param("text",originalText).
    when().
        get("http://md5.jsontest.com").
    then().
        assertThat().
        body("md5",equalTo(expectedMd5CheckSum));
}

Как видите, использовать параметры запроса в REST Assured очень просто, для этого нужно указать их имя и значение с помощью метода param(). Параметры пути задаются аналогичным образом:

@Test
public void test_NumberOfCircuits_ShouldBe20_Parameterized() {
        
    String season = "2017";
    int numberOfRaces = 20;
        
    given().
        pathParam("raceSeason",season).
    when().
        get("http://ergast.com/api/f1/{raceSeason}/circuits.json").
    then().
        assertThat().
        body("MRData.CircuitTable.Circuits.circuitId",hasSize(numberOfRaces));
}

Вместо param() параметры пути определяются с помощью метода pathParam(). Кроме того, вам необходимо определить, какая часть конечной точки представляет собой переменную path, что делается с помощью фигурных скобок. Таким же образом можно создать более одного параметра пути и даже объединить эти параметры в одном запросе.

Теперь, когда мы параметризовали тест, наполнить его набором тестовых данных — несложная задача. В TestNG достаточно создать объект DataProvider, содержащий необходимые тестовые данные, в нашем случае — это набор данных, содержащий годы и количество гонок Формулы-1 в каждом из них:

@DataProvider(name="seasonsAndNumberOfRaces")
public Object[][] createTestDataRecords() {
    return new Object[][] {
        {"2017",20},
        {"2016",21},
        {"1966",9}
    };
}

Затем просто передаем тестовые данные параметризованному тесту с помощью основных методов REST Assured:

@Test(dataProvider="seasonsAndNumberOfRaces")
public void test_NumberOfCircuits_ShouldBe_DataDriven(String season, int numberOfRaces) {
                
    given().
        pathParam("raceSeason",season).
    when().
        get("http://ergast.com/api/f1/{raceSeason}/circuits.json").
    then().
        assertThat().
        body("MRData.CircuitTable.Circuits.circuitId",hasSize(numberOfRaces));
}

Теперь вы можете добавлять, удалять или обновлять отдельные тест-кейсы, просто создавая или изменяя соответствующую запись.

Доступ к защищенным API

Часто API защищены с помощью механизма аутентификации. REST Assured поддерживает базовую, дайджест и OAuth аутентификацию. Вот пример вызова RESTful API, защищённого с помощью базовой аутентификации (т. е. пользователь этого API должен предоставлять правильное имя и пароль при каждом вызове API):

@Test
public void test_APIWithBasicAuthentication_ShouldBeGivenAccess() {
        
    given().
        auth().
        preemptive().
        basic("username", "password").
    when().
        get("http://path.to/basic/secured/api").
    then().
        assertThat().
        statusCode(200);
}

Получить доступ к API, защищенному OAuth2, просто, если у вас есть действительный токен аутентификации:

@Test
public void test_APIWithOAuth2Authentication_ShouldBeGivenAccess() {
        
    given().
        auth().
        oauth2(YOUR_AUTHENTICATION_TOKEN_GOES_HERE).
    when().
        get("http://path.to/oath2/secured/api").
    then().
        assertThat().
        statusCode(200);
}

Передача значений между тестами

Часто при тестировании RESTful API возникает необходимость в создании более сложных тест-кейсов. В них требуется получить значение из ответа одного вызова API и повторно использовать его в следующем вызове. Это можно сделать с помощью метода extract(). В качестве примера приведён сценарий, который извлекает идентификатор первой трассы сезона 2017 года и использует его для получения и проверки дополнительной информации об этой трассе (в данном случае трасса находится в Австралии):

@Test
public void test_ScenarioRetrieveFirstCircuitFor2017SeasonAndGetCountry_ShouldBeAustralia() {
        
    // First, retrieve the circuit ID for the first circuit of the 2017 season
    String circuitId = given().
    when().
        get("http://ergast.com/api/f1/2017/circuits.json").
    then().
        extract().
        path("MRData.CircuitTable.Circuits.circuitId[0]");
        
    // Then, retrieve the information known for that circuit and verify it is located in Australia
    given().
        pathParam("circuitId",circuitId).
    when().
        get("http://ergast.com/api/f1/circuits/{circuitId}.json").
    then().
        assertThat().
        body("MRData.CircuitTable.Circuits.Location[0].country",equalTo("Australia"));
}

Повторное использование проверок с помощью ResponseSpecBuilder

Ещё один способ улучшить многократное использование ваших тестов RESTful API — это повторное использование определённых проверок. Например, если вы хотите удостовериться, что все получаемые ответы имеют код состояния, равный 200, а их формат соответствует "application/json". Проверка этого для каждого теста может быть очень утомительна.

REST Assured поддерживает повторное использование определенных проверок с помощью механизма ResponseSpecBuilder.

Вот пример того, как создать повторно используемую ResponseSpecification, проверяющую код состояния и формат содержимого ответов:

ResponseSpecification checkStatusCodeAndContentType = 
    new ResponseSpecBuilder().
        expectStatusCode(200).
        expectContentType(ContentType.JSON).
        build();
Test
public void test_NumberOfCircuits_ShouldBe20_UsingResponseSpec() {
        
    given().
    when().
        get("http://ergast.com/api/f1/2017/circuits.json").
    then().
        assertThat().
        spec(checkStatusCodeAndContentType).
    and().
        body("MRData.CircuitTable.Circuits.circuitId",hasSize(20));
}

Другие возможности REST Assured

Помимо уже описанных, REST Assured предлагает ряд других полезных функций:

  • Возможность (де-) сериализации Java-объектов (POJO). Это позволяет вам перевести свойства и значения Java-объекта, в JSON или XML документ и наоборот. Затем этот документ можно отправить с помощью метода POST.
  • Сохранение запросов и ответов. Это полезно, если нужно просмотреть ответы API для создания соответствующих проверок, или убедиться, что отправленный запрос корректен.
  • REST Assured поставляется с модулем Spring Mock MVC, позволяющим писать тесты для контроллеров Spring, используя синтаксис REST Assured.

Перевод статьи Bas Dijkstra «How to perform API testing with REST Assured».

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

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

Читать в телеграм

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *