REST-assured: полезные советы

В данной статье я собрал полезные советы по использованию REST-assured, одной из самых распространенных Java-библиотек для автоматизации тестирования REST-API.

Все примеры жизненные, они собраны из моей практики проведения code-review в более чем 50 проектах с автотестами.

Выносите end-point’ы в отдельное место

Казалось бы, что это очевидно. Но нет, довольно часто приходится видеть код с захардкоженными end-point’ми в запросе.

Лучше всего выносить end-point’ы в статические константы финального класса. При этом стоит избегать антипаттерн «константный интерфейс» — это плохая практика.

Не забывайте, что REST-assured позволяет выносить параметры пути, например:

public final class EndPoints {     public static final String users = "/users/{id}"; ... }  given().pathParams("id", someId).get(EndPoints.users)...;  // или так  given().get(EndPoints.users, someId).... 

Также, если во многих запросах вы используете один и тот же базовый путь, то будет хорошей практикой вынести его в отельную константу и передавать в basePath, например:

// имеем следующий url приложения http://host:port/appname/rest/someEndpoints  private static final basePath = "/appname/rest/";  ..  // можем задать базовый путь на глобальном уровне, // он будет применяться ко всем запросам: RestAssured.basePath = basePath;  // или на уровне одного запроса: given().basePath(basePath)...  // или на уровне спецификации, но об этом далее 

То же самое применимо к хосту и порту тестируемого приложения.

ContentType/Accept

Данные заголовки используются практически во всех HTTP-запросах. Авторы REST-assured, понимая это, сделали возможным их установку через вызов специальных методов:

// плохая практика написания: given().header("content-type", "application/json").header("accept", "application/json")...;  // хорошая практика написания: given().contentType(ContentType.JSON).accept(ContentType.JSON)...; 

Хорошей практикой будет установить данные заголовки в спецификации или на глобальном уровне. Это повысит читабельность вашего кода.

StatusCode и т.п.

REST-assured предоставляет удобный синтаксис для проведения проверки каждой составляющей HTTP-ответа, однако на практике продолжаешь встречать подобный код:

// плохая практика написания: Response response = given()...when().get(someEndpoint); Assert.assertEquals(200, response.then().extract().statusCode());  // хорошая практика написания: given()...when().get(someEndpoint).then().statusCode(200); 

Используйте спецификации

Дублирование кода — это плохо. Используйте спецификации для уменьшения дублирования. В REST-assured можно создавать спецификации как для запроса, так и для ответа. В спецификацию запроса выносим всё, что может быть продублировано в запросах.

RequestSpecification requestSpec = new RequestSpecBuilder()     .setBaseUri("http://localhost")     .setPort(8080)     .setAccept(ContentType.JSON)     .setContentType(ContentType.ANY) ...     .log(LogDetail.ALL)     .build();  // можно задать одну спецификацию для всех запросов: RestAssured.requestSpecification = requestSpec;  // или для отдельного: given().spec(requestSpec)...when().get(someEndpoint); 

В спецификацию ответа выносим все проверки, которые дублируются от запроса к запросу.

ResponseSpecification responseSpec = new ResponseSpecBuilder()     .expectStatusCode(200)     .expectBody(containsString("success"))     .build();  // можно задать одну спецификацию для всех ответов: RestAssured.responseSpecification = responseSpec;  // или для отдельного: given()...when().get(someEndpoint).then().spec(responseSpec)...; 

Можно создавать несколько спецификаций для разных типов запросов/ответов и использовать в нужной ситуации.

Не пишите свои костыли для преобразования объектов

Не стоит преобразовывать свои POJO в JSON при помощи Jackson ObjectMapper’а, а потом полученную строку передавать в тело запроса. REST-assured прекрасно справляется с этой задачей. Для этого используется всё тот же Jackson или Gson, в зависимости от того, что находится в classpath. Для преобразования в XML используется JAXB. Исходный формат определяется автоматически по значению Content-Type.

given().contentType(ContentType.JSON).body(somePojo)     .when().post(EndPoints.add)     .then()     .statusCode(201);  // то же самое работает и в обратную сторону: SomePojo pojo = given().     .when().get(EndPoints.get)     .then().extract().body().as(SomePojo.class); 

Кроме того REST-assured прекрасно справляется с преобразованием HashMap в JSON и обратно.

Используйте всю мощь Groovy

Сама библиотека REST-assured написана на Groovy и позволяет вам применять различные методы из Groovy к полученному JSON/XML ответу. Например:

// методы find, findAll применяются к коллекции для поиска первого и всех вхождений, метод collect для  создания новой коллекции из найденных результатов.   // переменная it создается неявно и указывает на текущий элемент коллекции Map<String, ?> map = get(EndPoints.anyendpoint).path("rootelement.find { it.title =~ 'anythingRegExp'}");  // можете явно задать название переменной, указывающей на текущий элемент Map<String, ?> map = get(EndPoints.anyendpoint).path("rootelement.findAll { element -> element.title.length() > 4 }");  // вы можете использовать методы sum, max, min для суммирования всех значений коллекции, а также поиска максимального и минимально значения  String expensiveCar = get(EndPoints.cars).path("cars.find { it.title == 'Toyota Motor Corporation'}.models.max { it.averagePrice }.title"); 

Использование методов из Groovy позволяет сильно сократить количество кода, написанного вами для поиска необходимого значения из ответа.

На этом всё, если у вас есть еще советы и примеры пишите их в комментариях.

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

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