тестирование 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».

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

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