Back to guides

GUIDE / api

Karate Framework Tutorial: API Tests with BDD-Style Syntax

Karate framework tutorial for API testing with setup, feature files, assertions, data-driven tests, auth, mocks, CI, and mistakes.

By The Testing AcademyPublished July 10, 2026Updated July 10, 202614 min read

Karate framework tutorial searches usually come from testers who want API automation without writing a lot of Java boilerplate. Karate gives you a readable DSL for HTTP requests, assertions, data-driven tests, setup reuse, mocks, and CI execution. It is especially attractive when manual testers, automation testers, and developers need to review API tests together.

This guide teaches Karate from a practical QA perspective. You will learn when to use it, how feature files work, how to send requests, how to write assertions, how to handle authentication, how to design reusable tests, and which mistakes make Karate suites hard to maintain.

Karate Framework Tutorial: What Makes Karate Different

In this Karate framework tutorial, the goal is to build readable API tests that express behavior without hiding everything behind Java code. Karate uses Gherkin-like feature files, but it is not traditional BDD in the strict product-collaboration sense. It is a powerful API testing DSL that happens to use Feature, Scenario, Given, When, and Then syntax.

Example:

Feature: Users API

Scenario: Get user by id
  Given url baseUrl
  And path 'users', 123
  When method get
  Then status 200
  And match response.id == 123
  And match response.status == 'active'

That is compact and readable. A tester can understand the request and assertions without scanning a page of Java setup. Karate also supports variables, JSON matching, data-driven tests, reusable calls, hooks, tags, and reports.

If you need API testing fundamentals first, read API testing tutorial. Karate makes test writing easier, but it does not replace knowing HTTP, JSON, status codes, auth, and test design.

When to Choose Karate

Karate is a strong fit when:

  • The team wants readable API tests.
  • Testers are comfortable with structured feature files.
  • Java boilerplate is slowing the team down.
  • API tests need strong JSON assertions.
  • Data-driven examples are common.
  • Both technical and semi-technical reviewers need to read tests.
  • The suite should run in CI through Maven or Gradle.

Karate may be less ideal when:

  • The team already has a mature Java framework with Rest Assured.
  • Tests need complex custom programming.
  • Developers strongly prefer code-first test design.
  • The team uses another language ecosystem completely.
  • Feature files become dumping grounds for too much logic.

Comparison:

AreaKarateRest Assured
Test styleDSL feature filesJava code
Beginner readabilityHighMedium
Custom architectureModerateHigh
JSON matchingVery strongStrong
Java knowledge requiredLower for basic testsHigher
Best team fitQA-heavy API automationJava SDET or backend teams

For Rest Assured examples, see Rest Assured tutorial.

Project Setup

Karate commonly runs with Maven or Gradle. A Maven project includes Karate dependencies and a test runner.

Example dependency concept:

<dependency>
  <groupId>io.karatelabs</groupId>
  <artifactId>karate-junit5</artifactId>
  <version>1.5.0</version>
  <scope>test</scope>
</dependency>

Typical structure:

src/test/java
  users/
    UsersRunner.java
src/test/resources
  karate-config.js
  users/
    users.feature
  payloads/
    create-user.json

The runner connects JUnit to feature files:

class UsersRunner {
    @Karate.Test
    Karate testUsers() {
        return Karate.run("users").relativeTo(getClass());
    }
}

Follow your repository's build conventions. Do not add a separate layout if the project already has an established test structure.

Configuration with karate-config.js

Karate uses karate-config.js for environment configuration. This is where you set base URLs, common variables, and environment-specific values.

function fn() {
  var env = karate.env || 'qa';

  var config = {
    env: env,
    baseUrl: 'https://qa-api.example.com'
  };

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

  return config;
}

Run with:

mvn test -Dkarate.env=staging

Keep secrets out of committed config. Use CI secrets, environment variables, or secure secret management. Configuration should make environment switching easy and safe.

Writing Requests

Karate makes HTTP request construction concise.

GET request:

Scenario: List active users
  Given url baseUrl
  And path 'users'
  And param status = 'active'
  When method get
  Then status 200
  And match response.items == '#[]'

POST request:

Scenario: Create user
  Given url baseUrl
  And path 'users'
  And request
  """
  {
    "name": "QA User",
    "email": "qa.user@example.com",
    "role": "viewer"
  }
  """
  When method post
  Then status 201
  And match response.email == 'qa.user@example.com'
  And match response.id == '#present'

Karate's embedded JSON handling is one of its strengths. You can define payloads inline or load them from files.

Matching and Assertions

Karate's match syntax is expressive.

Examples:

And match response.id == '#number'
And match response.name == '#string'
And match response.email == '#regex .+@.+'
And match response.items == '#[3]'
And match response.status == 'ACTIVE'
And match response contains { role: 'admin' }

Use matchers to assert structure and behavior. Avoid asserting every field in every test. If a test is about user creation, assert the created fields and important defaults. Use schema-style matching for contract checks.

Example schema:

* def userSchema =
"""
{
  id: '#number',
  name: '#string',
  email: '#string',
  status: '#string'
}
"""
Then match response == userSchema

For deeper schema validation ideas, read JSON schema validation in API testing.

Authentication

Karate can request tokens and reuse them. A common pattern is to create a reusable auth feature.

auth.feature:

Feature: Auth helper

Scenario: Get access token
  Given url baseUrl
  And path 'auth', 'token'
  And request { username: '#(username)', password: '#(password)' }
  When method post
  Then status 200
  * def token = response.access_token

Use it in another feature:

* def auth = call read('classpath:auth/auth.feature') { username: 'admin', password: 'secret' }
* def token = auth.token

Given url baseUrl
And path 'account'
And header Authorization = 'Bearer ' + token
When method get
Then status 200

In real projects, credentials should come from secure config. Also create tests for invalid, expired, and missing tokens. Do not test only the happy path.

Data-Driven Testing

Karate supports scenario outlines:

Scenario Outline: Create user validation
  Given url baseUrl
  And path 'users'
  And request { name: <name>, email: <email>, role: <role> }
  When method post
  Then status <status>

Examples:
  | name      | email              | role     | status |
  | 'QA User' | 'qa@example.com'   | 'viewer' | 201    |
  | ''        | 'qa@example.com'   | 'viewer' | 400    |
  | 'QA User' | 'bad-email'        | 'viewer' | 400    |
  | 'QA User' | 'qa@example.com'   | 'bad'    | 400    |

Data-driven tests are useful for validation rules, enum values, roles, and boundaries. Keep examples focused. If a table has too many columns, split it by behavior.

Karate can also read JSON or CSV data files. That is useful when business rules require larger data sets.

Reusable Features and Test Design

Karate's call feature is powerful, but overuse can make tests hard to follow. Reuse setup and common flows, not every tiny action.

Good reuse:

  • Get auth token.
  • Create test user.
  • Create test order.
  • Reset test data.
  • Load common schema.

Poor reuse:

  • A feature file that hides all assertions.
  • Nested calls three levels deep.
  • Generic "do request" features that obscure behavior.

Tests should still read clearly. A reviewer should understand what behavior is being verified without opening ten helper files.

For broader structure, see API automation framework.

Negative Testing with Karate

Karate is excellent for negative API tests because payload variation is easy.

Test:

  • Missing required fields.
  • Invalid data types.
  • Invalid enum values.
  • Unauthorized requests.
  • Forbidden role access.
  • Unknown resource IDs.
  • Duplicate resources.
  • Malformed JSON.

Example:

Scenario: Missing email is rejected
  Given url baseUrl
  And path 'users'
  And request { name: 'No Email', role: 'viewer' }
  When method post
  Then status 400
  And match response.error.code == 'VALIDATION_ERROR'
  And match response.error.fields.email contains 'required'

Assert stable error codes. Full message text can be brittle unless exact wording is part of the contract.

Tags and CI Execution

Use tags to control suites:

@smoke
Scenario: Health endpoint works
  Given url baseUrl
  And path 'health'
  When method get
  Then status 200

Run selected tags in CI:

mvn test -Dkarate.options="--tags @smoke"

Suggested tags:

  • @smoke
  • @regression
  • @negative
  • @auth
  • @contract
  • @slow
  • @destructive

Do not run destructive tests against production-like environments without guardrails. Delete operations, billing operations, and admin changes need explicit environment protection.

Reporting and Debugging Karate Tests

Karate produces useful reports, but teams still need to design for debugability. When a test fails in CI, the report should show the feature, scenario, request method, URL, sanitized request body, response status, response body, and assertion failure. Without that evidence, testers must rerun locally just to understand the problem.

Use Karate's logging carefully. During local development, request and response logs can be helpful. In CI, avoid exposing tokens, passwords, personal data, or payment information. If your suite handles sensitive data, add redaction rules or keep payloads synthetic.

When debugging, classify failures:

FailureLikely Cause
Status mismatchEndpoint behavior, auth, or environment issue
Match failureContract or business assertion changed
Connection errorEnvironment, routing, or deployment issue
Token failureCredentials, auth helper, or secret config issue
Random data conflictTest data isolation problem

Do not immediately weaken match assertions. First decide whether the API changed intentionally, the test data is wrong, or the product has a defect.

Organizing Karate Feature Files

Feature organization matters as the suite grows. A common pattern is to group by domain or resource:

features/
  auth/
    login.feature
    token-negative.feature
  users/
    create-user.feature
    get-user.feature
    user-validation.feature
  orders/
    create-order.feature
    cancel-order.feature
    order-state-transitions.feature

Keep one feature file focused. A file called all-api-tests.feature becomes impossible to review. A file called user-validation.feature tells reviewers what behavior it protects.

Use background sections for setup that applies to every scenario in that feature:

Background:
  * url baseUrl
  * def auth = call read('classpath:auth/token.feature')
  * header Authorization = 'Bearer ' + auth.token

Do not put expensive setup in a background if only one scenario needs it. That slows every scenario and hides dependencies.

Working with External Test Data

Karate can read JSON files, CSV files, and JavaScript helpers. Use external files when payloads are large or reused.

Example:

* def payload = read('classpath:payloads/create-user.json')
* payload.email = 'qa-' + java.util.UUID.randomUUID() + '@example.com'
Given request payload
When method post
Then status 201

External payloads should still be reviewed. A large JSON file can hide irrelevant fields, stale values, or copied production data. Keep fixture names meaningful and avoid real personal data.

For validation testing, small inline payloads are often clearer. For complex business objects, external templates are easier to maintain. Choose based on readability.

Karate Mocks

Karate can also create mocks. This is useful when a dependency is unavailable or when you need controlled responses.

Mocking helps test:

  • Third-party API downtime.
  • Slow response.
  • Specific error code.
  • Rare payload variation.
  • Consumer behavior before provider is ready.

Still run real integration tests. Mocks can drift. If you need a broader mocking strategy, see API mocking with WireMock.

Karate for Contract and Smoke Suites

Karate works well for smoke suites because scenarios are concise. A smoke suite should prove that critical endpoints are alive, authenticated, and returning usable responses. It should not include every validation rule.

Contract-style Karate tests can validate response shape with matchers:

Then match response ==
"""
{
  id: '#number',
  email: '#string',
  status: '#(allowedStatuses.includes(response.status) ? response.status : karate.fail("bad status"))'
}
"""

Keep contract checks readable. If match logic becomes too clever, future maintainers will struggle. Sometimes a separate JSON schema or helper is clearer.

A practical split:

  • Smoke features run after deployment.
  • Regression features run before release.
  • Negative features run nightly or on relevant changes.
  • Contract features run when API schema changes.
  • Destructive features run only in isolated environments.

Common Mistakes in Karate Frameworks

The first mistake is treating Karate as pure BDD. Feature files should be readable, but API automation still needs technical assertions, data setup, and framework discipline.

The second mistake is putting too much logic in feature files. If a scenario becomes a script full of conditionals, split setup or rethink the test.

The third mistake is using one giant feature file. Organize by API domain and behavior.

The fourth mistake is hardcoding environment URLs and secrets. Use karate-config.js and secure injection.

The fifth mistake is overusing shared state. Tests should be independent where possible.

The sixth mistake is asserting only status codes. Karate makes JSON assertions easy, so use them.

The seventh mistake is hiding failures. Reports should include enough request and response detail to debug.

The eighth mistake is creating huge examples tables that nobody reviews. Keep data-driven tests focused.

The ninth mistake is hiding too much in reusable calls. Reuse should reduce noise, not make the scenario unreadable.

The tenth mistake is skipping code review because tests look like plain English. Karate tests are executable code and deserve the same review discipline as Java or JavaScript tests.

Karate Review Checklist

Before merging a Karate test, review it like production test code.

AreaReview Question
Scenario nameDoes it describe the behavior clearly?
SetupIs the data arranged inside the test or through a clear helper?
RequestAre path, params, headers, and body visible enough to review?
AssertionDoes it check business behavior, not only status?
DataIs test data unique or safely reusable?
AuthAre credentials secure and role assumptions clear?
TagsIs the scenario in the right suite?
CleanupDoes created state need removal or isolation?
LogsWill CI failure evidence be useful and safe?

This checklist prevents the most common Karate problem: readable syntax hiding weak test design.

Example Learning Path for Beginners

If you are new to Karate, learn in this order:

  1. Write a GET request and assert status plus one field.
  2. Add query parameters and path parameters.
  3. Write a POST request with an inline JSON body.
  4. Move the payload into a JSON file.
  5. Add authentication through a reusable feature.
  6. Add a negative validation scenario.
  7. Add a scenario outline for boundary values.
  8. Add tags and run only smoke tests.
  9. Add the suite to CI.
  10. Review failures and improve reporting.

This path avoids jumping straight into complex reusable calls. Beginners need to see how requests, responses, and assertions work before building framework helpers.

When Karate Is Not Enough

Karate covers many API automation needs, but some testing still belongs elsewhere. Use performance tools for serious load and latency testing. Use dedicated security tools and manual security review for deep vulnerability testing. Use Pact or provider-specific contract tooling when consumer-driven contracts are required. Use manual exploration when the API is poorly documented and risks are not understood yet.

A strong QA engineer knows where Karate fits and where another tool gives better signal. The goal is not to make every API quality problem look like a feature file. The goal is reliable evidence.

Where QABattle Fits in Your Practice

Karate is easy to write, but good API tests still require judgment. Practice identifying what to assert, what data matters, and what failure mode should be covered. The QABattle testing battles help you practice that reasoning under constraints.

Karate framework tutorial work should end with a suite that is readable, version-controlled, and useful in CI. Use Karate's DSL to reduce boilerplate, but keep test design disciplined: clear scenarios, meaningful assertions, controlled data, secure configuration, and focused tags.

As the suite grows, schedule periodic cleanup. Remove duplicate scenarios, rename vague feature files, tighten weak assertions, archive obsolete payloads, and review slow tests. Karate makes it easy to create tests quickly, so maintenance discipline is what keeps the framework valuable after the first few releases.

A good Karate suite should feel like executable API documentation. A new tester should be able to open a feature file, understand the endpoint behavior, see the important data, and know what failure would mean. If that is true, the framework is serving both automation and team communication.

FAQ

Questions testers ask

What is the Karate framework used for?

Karate is used for API testing, API automation, mocks, performance test integration, and some UI automation. It provides a readable DSL where testers can write HTTP requests, assertions, data-driven tests, and setup logic without heavy Java code.

Is Karate better than Rest Assured?

Karate is often easier for teams that want readable feature files and less Java code. Rest Assured is better for teams that prefer code-first Java frameworks with deeper custom architecture. The better choice depends on team skill, maintainability, and project ecosystem.

Do I need to know Java for Karate?

You do not need deep Java knowledge to write basic Karate API tests, but Java knowledge helps with project setup, custom utilities, CI integration, and advanced framework work. Karate is designed to keep most API tests readable in feature files.

Can Karate do data-driven testing?

Yes. Karate supports scenario outlines, examples tables, JSON and CSV data, dynamic payloads, reusable feature calls, and JavaScript expressions. This makes it practical for testing validation rules, multiple roles, payload variations, and negative cases.

Can Karate run in CI/CD?

Yes. Karate tests can run through Maven, Gradle, JUnit, command-line runners, and CI systems. Teams commonly tag tests as smoke, regression, or negative, then run selected suites in deployment pipelines.