Karate — тестирование API и UI

Продолжительность: 18 уроков · Уровень: средний

Karate — это фреймворк для тестирования веб-сервисов и интерфейсов. Тесты пишутся на читаемом языке сценариев, который понимает даже нетехнический аналитик, при этом за сценарием — полноценный REST-клиент, встроенные JSON-выражения и параллельный запуск.

1. Что такое Karate

Главное преимущество — тест выглядит как короткий текст, а вся работа с HTTP и JSON прячется за «волшебными» шагами.

2. Установка

Проще всего использовать автономный JAR:

wget https://github.com/karatelabs/karate/releases/latest

Или положить зависимости в pom.xml:

<dependency>
    <groupId>com.intuit.karate</groupId>
    <artifactId>karate-junit5</artifactId>
    <version>1.4.1</version>
    <scope>test</scope>
</dependency>
Для запуска нужна Java 8 и выше. Если Java нет — посмотри урок про IntelliJ IDEA и установи JDK оттуда.

3. Первый сценарий

Сценарий живёт в файле с расширением .feature:

Feature: проверка API

  Scenario: получаем пользователя
    Given url 'https://jsonplaceholder.typicode.com/users/1'
    When method get
    Then status 200
    And match $.name == 'Leanne Graham'

Выполняется сценарий одним Java-классом:

import com.intuit.karate.junit5.Karate;

class UsersTest {

    @Karate.Test
    Karate testAll() {
        return Karate.run("users").relativeTo(getClass());
    }
}

4. Шаги: Given / When / Then

Ключевое словоНазначение
Givenподготовить запрос: url, headers, параметры
Whenвыполнить действие: method get/post/put/delete
Thenпроверить ответ: status, headers, body
And / Butдобавить ещё один шаг любого типа
Given url baseUrl + '/products'
And header Authorization = 'Bearer ' + token
And request { name: 'Чашка', price: 990 }
When method post
Then status 201
And match response.id != null

5. Работа с JSON

JSON — «родной» формат Karate, обращаться к полям можно без приведения типов:

Given url baseUrl + '/users/2'
When method get
Then status 200
And match response.address.city == 'Wisokyburgh'
And match response.email == '#regex ^.+@.+\..+$'
And assert response.company.name != null

Выражения JsonPath

Then match $.id == 2
And match $..city == 'Wisokyburgh'
And match response[0].price >= 100
#regex — специальный «мягкий» маркер: он проверяет формат значения, а не равенство. Полезно для id, дат и email.

6. Параметризация

Для проверки множества значений используется Scenario Outline:

Scenario Outline: логин пользователя
  Given url baseUrl + '/login'
  And request { username: '<user>', password: '<pass>' }
  When method post
  Then status <code>

  Examples:
    | user    | pass   | code |
    | admin   | admin  | 200  |
    | bob     | wrong  | 401  |
    | maria   | secret | 403  |

Плейсхолдеры в угловых скобках подставляются из таблицы Examples.

7. Переменные и окружение

Общие данные выносятся в файл конфигурации karate-config.js:

function fn() {
  var env = karate.env || 'dev';
  var config = {
    baseUrl: 'https://dev.api.example.com',
    token: 'test-token'
  };
  if (env === 'prod') {
    config.baseUrl = 'https://api.example.com';
  }
  karate.configure('connectTimeout', 5000);
  return config;
}

Запуск с нужным окружением:

mvn test -Dkarate.env=prod

8. Чтение данных из файлов

Given url baseUrl + '/users/bulk'
And request read('data/users.json')   // из файла
When method post
Then status 200

// CSV так же легко:
* def rows = read('data/prices.csv')
Файлы можно хранить рядом со сценарием, пути задаются относительно текущего .feature-файла.

9. Отчёты и параллельный запуск

JUnit бежит по всем сценариям; по умолчанию Karate выдаёт консольный отчёт и красивые HTML-отчёты в target/karate-reports.

// параллельный запуск через maven-surefire
mvn test -Dkarate.options='--tags @smoke'

Теги

@smoke
Scenario: быстрая проверка
  ...

@regression @slow
Scenario: тяжёлый сценарий
  ...

10. Интеграция с CI

Karate запускается как обычный Maven-тест, поэтому встраивается в GitLab CI без дополнительных инструментов:

api-tests:
  stage: test
  image: maven:3.9-eclipse-temurin-17
  script:
    - mvn test -Dkarate.env=dev
  artifacts:
    paths:
      - target/karate-reports
Начни с API-тестов: они быстрые и стабильные. UI-тесты добавляй позже и покрывай только ключевые пользовательские сценарии.

11. Валидация ответов через match

Ключевой оператор Karate — match: он сравнивает ответ с шаблоном по частям, не требуя точного равенства всех полей:

* def response = { "user": { "id": 1, "name": "Ivan" } }
* match response contains { user: { id: 1 } }
* match response.user.name == "Ivan"

Для схем с типами используй маркеры: #string, #number, #boolean, #array:

* def userSchema = { id: "#number", name: "#string", roles: "#array" }
* match response.user == userSchema
Стабильность теста выше, если проверять контракт, а не дату или случайное значение: #string вместо «2026-09-19» защитит от поломок при изменении данных.

12. Авторизация: токены и refresh

Логин выносится в отдельный feature-файл и вызывается один раз через callonce, токен кладётся в заголовки через configure headers:

* configure headers = { Authorization: 'Bearer #(token)' }
* def result = callonce read('login.feature') { username: 'admin', password: 'secret' }
* def token = result.accessToken

Refresh-флоу проверяется отдельным сценарием: запрос с истёкшим токеном должен отдавать 401, а повторный логин — новый токен.

Не хардкодь пароли в feature-файлах: читай секреты из переменных окружения через karate.properties['key'] или конфиг-файл, который не попадает в Git.

13. Негативные сценарии и безопасность

Контракт API включает и проверку отказа. Покрывай неверные пейлоады, несуществующие ресурсы и битые токены:

Given url baseUrl + '/users/999'
When method get
Then status 404

Given path 'users'
And request { email: 'not-an-email' }
When method post
Then status 400
Не привязывайся к точным сообщениям об ошибках: валидируй диапазон кодов, а не текст, иначе регресс-тест сломается на первом изменении формулировки в бэкенде.

14. Окружения, теги и выборочный запуск

Окружения задаются в karate-config.json, а выбор — через переменную karate.env:

{
  "dev":     { "baseUrl": "https://dev-api.example.com" },
  "staging": { "baseUrl": "https://staging-api.example.com" }
}

Пометки @smoke, @regression на сценариях позволяют запускать только нужное:

КомандаДействие
mvn test -Dkarate.env=stagingзапуск на окружении staging
--tags @smokeтолько дымовые сценарии
--tags @a,@b --tags ~@slowнабор A/B без медленных
Перед прогоном на продакшене убедись, что тесты идемпотентны: повторный запуск не должен создавать дубликаты заказов или рассылать сообщения пользователям.

15. Ожидание и повторные попытки

API может отвечать не мгновенно: асинхронные задачи выполняются минуты, и сразу проверять статус нельзя. Karate поддерживает опрос через retry until — удобно для пайплайнов и транзакций:

Given url baseUrl + '/jobs/' + jobId
When method get
Then status 200
And retry until response.status == 'completed'

Шаг retry until повторяет последний HTTP-запрос, пока выражение не станет истинным. Параметры ожидания настраиваются глобально:

karate.configure('retry', { count: 20, interval: 3000 })
Не ставь бесконечные ретраи с крошечным интервалом — прод-сервис с 5-секундным ответом превратит тест в «висение», от которого будет страдать вся CI.

16. WebSocket и gRPC-протоколы

Не всё общение с API идёт по классическому REST: вебхуки в реальном времени и высоконагруженные сервисы используют WebSocket и gRPC. Karate умеет и то, и другое:

Given url 'ws://localhost:8080/socket'
When def socket = karate.webSocket(
And socket.send({ "type": "ping" })
And def reply = socket.receive()
Сильнее всего такие тесты выигрывают от связки с retry until из прошлого урока: вошёл — слушаешь — дождался ответа.

17. Смешивание с UI-тестами

Karate объединяет API и браузерные проверки: одна и та же сущность (токен, cookie) переходит из REST-вызовов в браузерные шаги.

Given driver 'https://app.example.com'
And input('#email', 'test@example.com')
And input('#password', 'secret')
And click('#login')
Then assert driver.waitUntil(() => karate.get('#dashboard') != null)

Скреиншоты добавляются тегом driver.screenshot(), элементы ищутся CSS/XPATH. Полезно переиспользовать уже созданный сеанс браузера между сценариями через общий конфиг.

Не дублируй UI-шагами то, что уже покрыл API: браузерные тесты дороже и хрупче, их место — лишь для интеграционных путей, где backend и frontend встречаются напрямую.

18. Частые ошибки и советы отладки

СимптомЧастая причинаРешение
Все сценарии падают одинаковоконфиг не подхватился (karate.env опечатка)проверь karate-config.js и тег запуска
match не совпадает, но данные «те же»разница типов: строка vs числоиспользуй #number/#string или #ignore
Периодичность: то зелёно, то красныйзависимость от порядка данных/временииди в retry until или фиксируй время в запросах
Тест «завис»нет таймаута в http callkarate.configure('connectTimeout', 5000)

Логи каждого шага пишутся в target/karate-reports/karate.log — там видно фактические запросы и ответы. Начинай отладку именно с лога, а не с глазами по зелёному diff.

Иногда среда теста висит из-за лимита памяти JVM: следи за Xmx в surefire, иначе краши начнутся вне зависимости от кода сценариев.

19. Переиспользование сценариев

Дублирование шагов — первый шаг к хрупким тестам. Karate позволяет выносить общую логику в отдельные feature и вызывать её из любого сценария.

* def token = callonce read('auth.feature')
* header Authorization = 'Bearer ' + token
Helper-фичи держите в отдельной папке common/ и не кладите туда assert-сценарии: они должны возвращать данные, а не проверять.

20. GraphQL-тесты

Karate работает с GraphQL напрямую: запросы уходят обычным POST с JSON-телом, а ответы разбираются матчерами.

Given path 'graphql'
And request { query: '#(query)', variables: '#(vars)' }
When method post
Then status 200
And match response.data.user.name == 'Ivan'
Проверяйте матчером, что errors пуст: иначе «молчаливый» сбой GraphQL пройдёт незамеченным.

21. Нагрузочные тесты с Karate Gatling

Те же feature-сценарии запускаются как нагрузочные через интеграцию Karate Gatling — без дублирования кода функциональных и перформанс-тестов.

val scn = karateFeature("classpath:tests.feature", "pets")
setUp(scn.inject(rampUsers(200).during(10))).protocols(karateProtocol())
Нагрузочный стенд должен быть изолирован: не гоняйте нагрузку по общему dev-окружению и фиксируйте состояние БД до прогона.

22. Окружения и контейнеры

Надёжные тесты требуют предсказуемого окружения. Поднимайте зависимости в Docker и перехватывайте трафик там, где это нужно.

docker run --rm -p 4444:4444 ghcr.io/karatelabs/karate-chrome
Для Chrome-сценариев используйте headless-режим karate-chrome: прогоны быстрее и стабильнее, чем с полным браузером.

Добавьте в CI кэширование образов и чистую сеть для контейнеров — это убирает большинство проблем «на моей машине работает».

Что дальше

Комбинируй Karate с JUnit для unit-тестов, GitLab CI для запуска и Docker для окружений. Полный список курсов — на главной странице.

← Вернуться к курсам