Перейти к основному содержимому

Тестирование REST API с помощью каратэ

· 5 мин. чтения

1. Обзор

В этой статье мы познакомим вас с Karate , средой тестирования Behavior Driven Development (BDD) для Java.

2. Каратэ и БДД

Karate построен на основе Cucumber , другой среды тестирования BDD , и использует некоторые из тех же концепций. Одним из таких является использование файла Gherkin, который описывает тестируемую функцию . Однако, в отличие от Cucumber, тесты написаны не на Java и полностью описаны в файле Gherkin.

Файл корнишона сохраняется с расширением « .feature» . Он начинается с ключевого слова Feature , за которым следует имя функции в той же строке. Он также содержит различные тестовые сценарии, каждый из которых начинается с ключевого слова « Сценарий » и состоит из нескольких шагов с ключевыми словами « Дано », « Когда », « Тогда », « И » и « Но » .

Подробнее о Cucumber и структуре Gherkin можно прочитать здесь .

3. Зависимости Maven

Чтобы использовать Karate в проекте Maven, нам нужно добавить зависимость karate-apache в pom.xml :

<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-apache</artifactId>
<version>0.6.0</version>
</dependency>

Нам также понадобится зависимость karate-junit4 для облегчения тестирования JUnit:

<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-junit4</artifactId>
<version>0.6.0</version>
</dependency>

4. Создание тестов

Мы начнем с написания тестов для некоторых распространенных сценариев в файле Gherkin Feature .

4.1. Тестирование кода состояния

Давайте напишем сценарий, который тестирует конечную точку GET и проверяет, возвращает ли она код состояния HTTP 200 (ОК):

Scenario: Testing valid GET endpoint
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200

Очевидно, что это работает со всеми возможными кодами состояния HTTP.

4.2. Тестирование ответа

Давайте напишем еще один сценарий, который проверяет, возвращает ли конечная точка REST определенный ответ:

Scenario: Testing the exact response of a GET endpoint
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ == {id:"1234",name:"John Smith"}

Операция сопоставления используется для проверки , где « представляет ответ. Таким образом, приведенный выше сценарий проверяет, что ответ точно соответствует ' {id:"1234",name:"John Smith"}'.

Мы также можем специально проверить значение поля id :

And match $.id == "1234"

Операцию сопоставления также можно использовать для проверки наличия в ответе определенных полей. Это полезно, когда нужно проверить только определенные поля или когда известны не все поля ответа:

Scenario: Testing that GET response contains specific field
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ contains {id:"1234"}

4.3. Проверка значений ответов с помощью маркеров

В случае, когда мы не знаем точное возвращаемое значение, мы все равно можем проверить значение с помощью маркеров — заполнителей для сопоставления полей в ответе.

Например, мы можем использовать маркер, чтобы указать, ожидаем ли мы нулевое значение или нет:

  • #нулевой
  • #ненулевой

Или мы можем использовать маркер для соответствия определенному типу значения в поле:

  • #логическое значение
  • #количество
  • #нить

Другие маркеры доступны, когда мы ожидаем, что поле будет содержать объект или массив JSON:

  • #множество
  • #объект

И есть маркеры для сопоставления с определенным форматом или регулярным выражением, а также тот, который оценивает логическое выражение:

  • #uuid — значение соответствует формату UUID
  • #regex STR — значение соответствует регулярному выражению STR
  • #? EXPR — утверждает, что выражение JavaScript EXPR оценивается как истинное .

Наконец, если мы не хотим проверять какое-либо поле, мы можем использовать маркер #ignore .

Давайте перепишем приведенный выше сценарий, чтобы проверить, что поле id не равно null :

Scenario: Test GET request exact response
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ == {id:"#notnull",name:"John Smith"}

4.4. Тестирование конечной точки POST с телом запроса

Давайте рассмотрим окончательный сценарий, который проверяет конечную точку POST и принимает тело запроса:

Scenario: Testing a POST endpoint with request body
Given url 'http://localhost:8097/user/create'
And request { id: '1234' , name: 'John Smith'}
When method POST
Then status 200
And match $ contains {id:"#notnull"}

5. Запуск тестов

Теперь, когда тестовые сценарии завершены, мы можем запустить наши тесты, интегрировав Karate с JUnit.

Мы будем использовать аннотацию @CucumberOptions , чтобы указать точное расположение файлов функций :

@RunWith(Karate.class)
@CucumberOptions(features = "classpath:karate")
public class KarateUnitTest {
//...
}

Чтобы продемонстрировать REST API, мы будем использовать сервер WireMock.

В этом примере мы имитируем все конечные точки, которые тестируются в методе, аннотированном @BeforeClass . Мы выключим сервер WireMock в методе, аннотированном @AfterClass :

private static WireMockServer wireMockServer
= new WireMockServer(WireMockConfiguration.options().port(8097));

@BeforeClass
public static void setUp() throws Exception {
wireMockServer.start();
configureFor("localhost", 8097);
stubFor(
get(urlEqualTo("/user/get"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{ \"id\": \"1234\", name: \"John Smith\" }")));

stubFor(
post(urlEqualTo("/user/create"))
.withHeader("content-type", equalTo("application/json"))
.withRequestBody(containing("id"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{ \"id\": \"1234\", name: \"John Smith\" }")));

}

@AfterClass
public static void tearDown() throws Exception {
wireMockServer.stop();
}

Когда мы запускаем класс KarateUnitTest , конечные точки REST создаются сервером WireMock, и запускаются все сценарии в указанном файле функций.

6. Заключение

В этом руководстве мы рассмотрели, как тестировать REST API с помощью Karate Testing Framework.

Полный исходный код и все фрагменты кода для этой статьи можно найти на GitHub .