Skip to main content

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
Important

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.featureuser-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

AspectCucumberKarate
Step DefinitionsRequired Java glue codeBuilt-in for HTTP/JSON/XML
Maintenance2 layers (feature + Java)Single layer (feature only)
Learning CurveComplex setupImmediate productivity
API TestingRequires REST AssuredNative 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
Background and Parallel Execution

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