CORE SYNTAX
Feature Files
Write tests using Gherkin syntax with built-in step definitions. Unlike traditional Cucumber, Karate requires no Java glue code - everything you need for API testing is included.
Basic Structure
Every Karate test follows this structure:
Feature: User Management API
Testing CRUD operations for user endpoints
Background: # Optional: Runs before EACH scenario
* def 'https://api.example.com'
* def authToken = 'bearer-token-123' * header Authorization = 'Bearer ' + authToken
Scenario: Create user with valid data
Given path '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' }
Scenario: Get user by ID
Given path 'users', 123
When method get
Then status 200
And match response.name == '#string'
The Three Sections
Feature Declaration
Describes the overall purpose:
Feature: Payment Processing API
Test payment workflows including validation,
processing, and error handling scenarios
Background (Optional)
Common setup that runs before each scenario:
Background:
* url 'https://api.example.com'
* def authToken = karate.callSingle('classpath:auth/get-token.feature')
* header Authorization = 'Bearer ' + authToken.token
* configure connectTimeout = 5000
Background variables are reset before each scenario. For one-time setup, use callonce
or karate.callSingle()
.
Scenarios
Individual test cases that run independently:
Scenario: Process valid payment
Given path 'payments'
And request { amount: 100.00, currency: 'USD', cardToken: 'tok_123' }
When method post
Then status 200
And match response.status == 'succeeded'
Naming Conventions
File Naming
- Feature files:
kebab-case.feature
(e.g.,user-authentication.feature
) - Descriptive names: Clearly indicate the feature area and purpose
- Avoid abbreviations:
user-mgmt.feature
→user-management.feature
Scenario Naming
# Good: Descriptive scenario names
Scenario: Create user with valid email address
Scenario: Update user profile with missing required fields
Scenario: Delete user removes all associated data
# Avoid: Generic or unclear names
Scenario: Test user creation
Scenario: User test 1
Scenario: Happy path
Given-When-Then vs Star (*)
Traditional BDD Style
Use when tests read like business requirements:
Scenario: User registration workflow
Given the user provides valid registration data
* def userData = { name: 'John', email: 'john@test.com' }
When the user submits the registration form
* url baseUrl
* path 'users/register'
* request userData
* method post
Then the user account is created successfully
* status 201
* match response.user.email == userData.email
Star (*) Notation
Use for technical, API-focused tests:
Scenario: API endpoint validation
* url baseUrl
* path 'users', userId
* method get
* status 200
* match response.id == userId
* assert responseTime < 1000
When to Use Which
- Given-When-Then: Business-readable scenarios, stakeholder communication
- Star (*): Technical API tests, Background sections, variable definitions
Script Structure
Karate vs Cucumber
Aspect | Cucumber | Karate |
---|---|---|
Step Definitions | Required Java glue code | Built-in for HTTP/JSON/XML |
Maintenance | 2 layers (feature + Java) | Single layer (feature only) |
Learning Curve | Complex setup | Immediate productivity |
API Testing | Requires REST Assured | Native HTTP support |
Comments and Documentation
Feature: Well-documented API tests
# This is a comment - ignored during execution
# Use comments to explain complex logic or business rules
Background: # Set up common configuration for all scenarios
* def baseUrl
* configure headers = { 'Content-Type': 'application/json' }
# Test user creation with various data scenarios
Scenario: Create user - happy path # Positive test case with valid data
* def validUser = { name: 'John', email: 'john@test.com' }
* path 'users'
* request validUser * def post * status 201
Advanced Features
Scenario Outline for Data-Driven Tests
Feature: Data-driven user validation
Scenario Outline: Validate user creation with different inputs
Given path 'users'
And request { name: '<name>', email: '<email>' }
When method post
Then status <expectedStatus>
Examples:
| name | email | expectedStatus |
| John | john@test.com | 201 |
| Jane | jane@test.com | 201 |
| | empty@test.com | 400 |
| Bob | invalid-email | 400 |
Tags for Organization
Feature: Tagged scenarios
@smoke @fast
Scenario: Quick health check
* def baseUrl
* path 'health'
* def get
* status 200
@regression @auth
Scenario: Complete authentication flow * call read('classpath:auth/full-login-flow.feature')
@integration @slow
Scenario: End-to-end user workflow # Complex scenario spanning multiple services
Best Practices
Independent Scenarios
# Good: Each scenario is independent
Feature: Independent user tests
Background: * def baseUrl
* def testUser = { name: 'Test User', email: 'test@example.com' }
Scenario: Create user
* path 'users'
* request testUser
* def post
* status 201
Scenario: Get user (independent - doesn't rely on previous scenario)
* path 'users', 123 # Use known ID, not from previous test
* def get * status 200
Clear Documentation
Feature: Payment API Integration
Comprehensive testing of payment processing workflows
including validation, authorization, and settlement
# This feature covers:
# - Payment creation and validation
# - Authorization and capture flows
# - Error handling for failed payments
# - Refund and cancellation scenarios
Background: # Common setup for all payment scenarios
* url paymentApiUrl
* call read('classpath:auth/payment-auth.feature')
Common Gotchas
- Background resets: Variables in Background are reset before each scenario
- Scenario independence: Each scenario should work standalone
- Variable scope: Variables don't carry over between scenarios
- Parallel execution: Scenarios may run in any order
Variables defined in Background
are reset before every Scenario. Combined with parallel execution, scenarios can run in any order on different threads.
Design for isolation:
- Each scenario must be runnable independently
- Don't share state between scenarios
- Don't depend on execution order
- Use
callonce
for one-time setup that needs to persist
See Variables and Parallel Execution for details.
Next Steps
Master feature file structure and continue with:
- Variables - Learn data management and manipulation
- Data Types - Handle JSON, XML, and complex data
- Actions - Master Karate's built-in keywords