TL;DR
- Karate = BDD API testing without Java coding (tests in
.featurefiles)- Syntax: Given/When/Then with built-in JSON/XML assertions
- No separate step definitions needed — assertions are built into DSL
- Includes mocking, performance testing, parallel execution
- Runs on JVM but tests written in Gherkin-like syntax
Best for: Teams wanting BDD without programming, rapid API test development
Skip if: Need full programmatic control (use REST Assured) Reading time: 14 minutes
Karate DSL is a BDD-style API testing framework used by thousands of enterprise teams who need rapid test development without dedicated Java expertise. According to the 2024 SmartBear State of API Testing report, BDD-style API test frameworks have seen 40% year-over-year growth in enterprise adoption. Unlike Cucumber, Karate requires no step definition files — assertions are built into the DSL, enabling testers to write complete API test suites in Gherkin-like syntax without writing a single line of Java. Karate supports REST, SOAP, GraphQL, WebSocket, and even browser automation in a single framework. This guide covers Karate from first feature file to production-grade test suites: JSON validation, data-driven tests, mocking, parallel execution, and CI/CD integration.
Your team wants BDD-style API tests but doesn’t have Java developers. Writing step definitions feels like boilerplate. You need something faster than traditional Cucumber setups.
Karate combines BDD syntax with built-in assertions — no glue code needed. Write tests in feature files, run them immediately. JSON matching, schema validation, data-driven testing all work out of the box.
What is Karate?
Karate is an open-source API testing framework that uses a Gherkin-like DSL. Unlike Cucumber, it doesn’t require step definitions — everything is built into the syntax.
Why Karate:
- No Java code — tests written in
.featurefiles - Built-in assertions — JSON/XML matching without code
- Parallel execution — fast test suite runs
- Mocking — built-in mock server
- Performance — load testing with Gatling integration
- UI testing — browser automation included
Setup
Maven
<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-junit5</artifactId>
<version>1.4.1</version>
<scope>test</scope>
</dependency>
Project Structure
src/test/java/
├── karate-config.js # Global config
├── logback-test.xml # Logging
└── examples/
├── users/
│ ├── users.feature # Test scenarios
│ └── UsersRunner.java # JUnit runner
└── products/
└── products.feature
JUnit 5 Runner
package examples.users;
import com.intuit.karate.junit5.Karate;
class UsersRunner {
@Karate.Test
Karate testUsers() {
return Karate.run("users").relativeTo(getClass());
}
}
Your First Test
Basic GET Request
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 with JSON Body
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
Exact Match
* match response == { id: 1, name: 'John', active: true }
Partial Match
* match response contains { name: 'John' }
Type Matching
# Match types with markers
* 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' # Optional (can be null)
Array Assertions
* match response == '#[3]' # Exactly 3 items
* match response == '#[]' # Any array
* match each response == { id: '#number' } # Each item matches
* match response contains { id: 1 } # Array contains item
* match response !contains { id: 999 } # Array doesn't contain
Nested JSON
* match response.user.address.city == 'New York'
* match response..name == ['John', 'Jane'] # All 'name' values
Variables and Reuse
Define Variables
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
Extract from Response
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'
Call Other 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 Testing
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 |
External Data Files
# Read from JSON file
* def testData = read('users-data.json')
Scenario Outline: Test with external data
Given url 'https://api.example.com/users'
And request <user>
When method post
Then status 201
Examples:
| user |
| { name: 'John', email: 'j@test.com' } |
| { name: 'Jane', email: 'jane@test.com' }|
Configuration
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';
}
// Global headers
karate.configure('headers', { 'Content-Type': 'application/json' });
return config;
}
Using Config in Tests
Feature: Users API
Background:
* url baseUrl + '/users'
Scenario: Get users
When method get
Then status 200
Parallel Execution
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 threads
assertEquals(0, results.getFailCount(), results.getErrorMessages());
}
}
Mock Server
Define Mock
Feature: Mock Server
Background:
* def port = 8080
* def mock = karate.start({ mock: 'mock.feature', port: port })
Scenario: Test with mock
Given url 'http://localhost:' + port + '/users'
When method get
Then status 200
mock.feature
Feature: Mock API
Scenario: pathMatches('/users')
* def response = [{ id: 1, name: 'Mock User' }]
Scenario: pathMatches('/users/{id}')
* def userId = pathParams.id
* def response = { id: '#(userId)', name: 'User ' + userId }
CI/CD Integration
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 with AI Assistance
AI tools can help write and maintain Karate tests.
What AI does well:
- Generate feature files from API documentation
- Create JSON match expressions
- Convert Postman collections to Karate
- Suggest data-driven test scenarios
What still needs humans:
- Designing test strategy
- Understanding business validation rules
- Complex conditional logic
- Performance test configuration
FAQ
What is Karate?
Karate is a BDD API testing framework using Gherkin-like DSL where assertions are built-in, requiring no Java step definitions.
Karate is a BDD API testing framework that uses Gherkin-like syntax. Unlike Cucumber, you don’t need Java step definitions — assertions are built into the DSL. Write Given/When/Then scenarios in .feature files and run them immediately. It also includes mocking, performance testing, and UI automation capabilities.
Karate vs REST Assured — which is better?
Choose Karate for teams without Java expertise; choose REST Assured for programmatic control and complex test logic.
Karate requires no Java programming — tests are written in .feature files using DSL syntax. REST Assured requires Java code for everything. Karate is faster to learn and easier for non-programmers. REST Assured offers more programmatic control and better IDE support. Choose Karate for rapid test development, REST Assured for complex programmatic needs.
Can Karate test GraphQL?
Yes — Karate handles GraphQL as standard JSON over HTTP, supporting queries, mutations, and variables natively.
Yes, Karate handles GraphQL as JSON over HTTP. Use the same request/response syntax for queries and mutations. GraphQL variables work through standard JSON handling. The framework doesn’t distinguish GraphQL from REST — it’s all HTTP with JSON bodies.
Does Karate support parallel execution?
Yes — Karate has built-in parallel execution; configure threads in the JUnit Runner class and Karate handles thread safety automatically.
Yes, parallel execution is built-in and easy to configure. Run features across multiple threads with a simple Runner configuration. Karate handles thread safety and resource isolation automatically. This makes it ideal for large test suites needing fast CI/CD feedback.
Official Resources
- Karate Documentation
- Karate GitHub — over 8,000 stars and active maintenance as of 2025
- SmartBear State of API Testing 2024 — 40% YoY growth in BDD-style API test adoption
“Karate removes the biggest barrier to BDD adoption: the glue code. When QA engineers can write complete API tests in feature files without programming, test coverage grows dramatically.” — Yuri Kan, Senior QA Lead
See Also
- API Testing Tutorial - API testing fundamentals
- REST Assured Tutorial - Java API testing
- Postman Tutorial - GUI-based API testing
- Cucumber Tutorial - BDD with step definitions
- API Testing Complete Guide - End-to-end API testing strategies
