TL;DR

  • Karate = BDD API тестирование без Java кода (тесты в .feature файлах)
  • Синтаксис: Given/When/Then со встроенными JSON/XML assertions
  • Отдельные step definitions не нужны — assertions встроены в DSL
  • Включает мокирование, нагрузочное тестирование, параллельное выполнение
  • Работает на JVM, но тесты пишутся в Gherkin-подобном синтаксисе

Идеально для: Команд, желающих BDD без программирования, быстрой разработки API тестов Пропусти, если: Нужен полный программный контроль (используй REST Assured) Время чтения: 14 минут

Твоя команда хочет BDD-стиль API тестов, но нет Java разработчиков. Написание step definitions кажется бойлерплейтом. Нужно что-то быстрее традиционных Cucumber настроек.

Karate сочетает BDD синтаксис со встроенными assertions — glue code не нужен. Пиши тесты в feature файлах, запускай сразу. JSON matching, валидация схем, data-driven тестирование — всё работает из коробки.

Что такое Karate?

Karate — open-source API тестирование фреймворк с Gherkin-подобным DSL. В отличие от Cucumber, не требует step definitions — всё встроено в синтаксис.

Почему Karate:

  • Без Java кода — тесты в .feature файлах
  • Встроенные assertions — JSON/XML matching без кода
  • Параллельное выполнение — быстрый запуск тест-сьютов
  • Мокирование — встроенный mock сервер
  • Performance — нагрузочное тестирование с Gatling интеграцией

Настройка

Maven

<dependency>
    <groupId>com.intuit.karate</groupId>
    <artifactId>karate-junit5</artifactId>
    <version>1.4.1</version>
    <scope>test</scope>
</dependency>

Структура проекта

src/test/java/
├── karate-config.js          # Глобальная конфигурация
├── logback-test.xml          # Логирование
└── examples/
    ├── users/
    │   ├── users.feature     # Тест-сценарии
    │   └── UsersRunner.java  # JUnit runner
    └── products/
        └── products.feature

Первый тест

Базовый GET запрос

Feature: User API

  Scenario: Get all users
    Given url 'https://api.example.com/users'
    When method get
    Then status 200
    And match response == '#array'
    And match each response contains { id: '#number', name: '#string' }

POST с JSON телом

Scenario: Create new user
  Given url 'https://api.example.com/users'
  And request { name: 'John Doe', email: 'john@example.com' }
  When method post
  Then status 201
  And match response contains { id: '#number', name: 'John Doe' }

JSON Assertions

Точное совпадение

* match response == { id: 1, name: 'John', active: true }

Частичное совпадение

* match response contains { name: 'John' }

Проверка типов

# Проверка типов с маркерами
* match response.id == '#number'
* match response.name == '#string'
* match response.email == '#? _.contains("@")'
* match response.roles == '#array'
* match response.metadata == '#object'
* match response.deleted == '#null'
* match response.optional == '##string'  # Опциональный (может быть null)

Assertions для массивов

* match response == '#[3]'                    # Ровно 3 элемента
* match response == '#[]'                      # Любой массив
* match each response == { id: '#number' }     # Каждый элемент соответствует
* match response contains { id: 1 }            # Массив содержит элемент
* match response !contains { id: 999 }         # Массив не содержит

Переменные и переиспользование

Определение переменных

Feature: User Management

  Background:
    * url 'https://api.example.com'
    * def authToken = 'Bearer abc123'

  Scenario: Get user profile
    Given path '/users/me'
    And header Authorization = authToken
    When method get
    Then status 200

Извлечение из ответа

Scenario: Create and fetch user
  Given url 'https://api.example.com/users'
  And request { name: 'John' }
  When method post
  Then status 201
  * def userId = response.id

  Given url 'https://api.example.com/users/' + userId
  When method get
  Then status 200
  And match response.name == 'John'

Вызов других features

# auth.feature
Feature: Authentication
  Scenario: Get token
    Given url 'https://api.example.com/auth'
    And request { username: 'test', password: 'secret' }
    When method post
    Then status 200
    * def token = response.token

# users.feature
Feature: Users
  Background:
    * def auth = call read('auth.feature')
    * def token = auth.token

  Scenario: Get protected resource
    Given url 'https://api.example.com/profile'
    And header Authorization = 'Bearer ' + token
    When method get
    Then status 200

Data-Driven тестирование

Scenario Outline

Feature: User validation

  Scenario Outline: Validate user creation
    Given url 'https://api.example.com/users'
    And request { name: '<name>', email: '<email>' }
    When method post
    Then status <status>

    Examples:
      | name  | email             | status |
      | John  | john@example.com  | 201    |
      | ''    | test@example.com  | 400    |
      | Jane  | invalid-email     | 400    |

Конфигурация

karate-config.js

function fn() {
  var env = karate.env || 'dev';
  var config = {
    baseUrl: 'https://api.example.com'
  };

  if (env === 'dev') {
    config.baseUrl = 'https://dev-api.example.com';
  } else if (env === 'staging') {
    config.baseUrl = 'https://staging-api.example.com';
  }

  karate.configure('headers', { 'Content-Type': 'application/json' });

  return config;
}

Параллельное выполнение

Parallel Runner

import com.intuit.karate.Results;
import com.intuit.karate.Runner;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class ParallelRunner {
    @Test
    void testParallel() {
        Results results = Runner.path("classpath:examples")
            .parallel(5);  // 5 потоков
        assertEquals(0, results.getFailCount(), results.getErrorMessages());
    }
}

CI/CD интеграция

GitHub Actions

name: API Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Run Karate tests
        run: mvn test -Dkarate.env=staging

      - name: Upload reports
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: karate-reports
          path: target/karate-reports/

Karate с помощью ИИ

ИИ инструменты могут помочь писать и поддерживать Karate тесты.

Что ИИ делает хорошо:

  • Генерировать feature файлы из API документации
  • Создавать JSON match выражения
  • Конвертировать Postman коллекции в Karate
  • Предлагать data-driven тест сценарии

Что требует людей:

  • Проектирование тест-стратегии
  • Понимание бизнес-правил валидации
  • Сложная условная логика
  • Конфигурация performance тестов

FAQ

Что такое Karate?

Karate — BDD фреймворк для API тестирования с Gherkin-подобным синтаксисом. В отличие от Cucumber, тебе не нужны Java step definitions — assertions встроены в DSL. Пиши Given/When/Then сценарии в .feature файлах и запускай их сразу. Также включает мокирование, нагрузочное тестирование и UI автоматизацию.

Karate vs REST Assured — что лучше?

Karate не требует Java программирования — тесты пишутся в .feature файлах с DSL синтаксисом. REST Assured требует Java код для всего. Karate быстрее изучить и проще для не-программистов. REST Assured даёт больше программного контроля и лучшую IDE поддержку. Выбирай Karate для быстрой разработки тестов, REST Assured для сложных программных нужд.

Может ли Karate тестировать GraphQL?

Да, Karate обрабатывает GraphQL как JSON over HTTP. Используй тот же синтаксис request/response для queries и mutations. GraphQL переменные работают через стандартную обработку JSON. Фреймворк не различает GraphQL от REST — это всё HTTP с JSON телом.

Поддерживает ли Karate параллельное выполнение?

Да, параллельное выполнение встроено и легко настраивается. Запускай features в нескольких потоках с простой конфигурацией Runner. Karate автоматически обрабатывает thread safety и изоляцию ресурсов. Это делает его идеальным для больших тест-сьютов, нуждающихся в быстром CI/CD фидбеке.

Официальные ресурсы

Смотрите также