Skip to main content

CORE SYNTAX

Variables

Store any data type - strings, JSON, XML, arrays - with zero boilerplate. Variables power Karate's dynamic testing, from simple values to complex API responses.

Setting and Using Variables

def - Variable Declaration

Use def to declare variables for strings, numbers, booleans, objects, or arrays. Variables help reuse common data across steps.

Gherkin
Feature: Variable basics

Scenario: Working with variables
# Strings
* def name = 'Alice'
* def greeting = 'Hello ' + name

# Numbers and booleans
* def id = 1
* def active = true

# JSON objects and arrays
* def user = { id: id, name: name, active: active }
* def ids = [1, 2, 3]

# XML
* def userXml = <user><id>1</id><name>Alice</name></user>
Reserved Variable Names

url and request are reserved keywords in Karate for HTTP operations. Do not use them as variable names.

Incorrect:

* def url = 'https://api.example.com'
* def request = { name: 'test' }

Correct:

* def apiUrl = 'https://api.example.com'
* def requestBody = { name: 'test' }

Using reserved keywords as variables leads to unclear tests and unexpected behavior.

Multi-Line Expressions

Use triple-quoted strings for large JSON or XML blocks to keep tests readable and maintainable.

Gherkin
Feature: Multi-line variables

Scenario: Define structured data clearly
# Multi-line JSON
* def user =
"""
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
"""

# Multi-line XML
* def userXml =
"""
<user>
<id>1</id>
<name>Alice</name>
</user>
"""

* match user.name == 'Alice'
* match userXml/user/name == 'Alice'

assert - Validation

assert is best for validating simple expressions or variables, especially when comparing numbers or performing logical checks.

Gherkin
Feature: Variable validation

Scenario: Validate user fields
* def user = { id: 123, name: 'John', age: 30 }

# Basic checks
* assert user.id == 123
* assert user.age > 18

# Combined conditions
* assert user.id > 0 && user.name.length > 0
Use match instead

You will rarely need assert in your test scripts. The match keyword is designed for powerful assertions against JSON and XML payloads and provides much better error messages.

Use print to output variable values for debugging:

Gherkin
Feature: Variable debugging

Scenario: Print variable values
* def user = { id: 123, name: 'John' }
* def scores = [85, 92, 78]
* def userXml =
"""
<user>
<name>John</name>
</user>
"""

# Print single values
* print 'User ID:', user.id
* print 'User name:', user.name

# Print full objects
* print 'Complete user:', user
* print 'Scores array:', scores

# Print multiple values in one line
* print 'User', user.name, 'has ID', user.id

# Pretty-print helpers
* print 'Formatted JSON:', karate.pretty(user)
* print 'Formatted XML:', karate.prettyXml(userXml)
Comma vs Concatenation

Use commas (not +) to pretty-print JSON and XML objects automatically.

table - Creating JSON Arrays

Use the table keyword to quickly build JSON arrays for test data.

Gherkin
Feature: Table to JSON conversion

Scenario: User list created from table
Feature: Table to JSON conversion

Scenario: User list created from table
* table users
| name | age | active |
| 'John' | 30 | true |
| 'Jane' | 25 | true |
| 'Bob' | 35 | false |

* match users[0].name == 'John'
* match users[1].age == 25
* match users[2].active == false

The table above becomes:

Gherkin
[
{ "name": "John", "age": 30, "active": true },
{ "name": "Jane", "age": 25, "active": true },
{ "name": "Bob", "age": 35, "active": false }
]
Empty Cells and Null Values

When converting tables to JSON:

• An empty cell means the key is omitted from the resulting object • (null) inserts a null value explicitly

* table users
| name | email |
| John | | # email key omitted
| Jane | (null) | # email set to null

Becomes:

 [
{ "name": "John" },
{ "name": "Jane", "email": null }
]

get - JsonPath Operations

get and $variable Shortcut

Karate supports both standard property access and powerful JsonPath expressions to extract values from JSON objects.

Gherkin
Feature: JsonPath extraction

Scenario: Access and extract fields
* def response =
"""
{
"users": [
{ "id": 1, "name": "John", "profile": { "email": "john@test.com" } },
{ "id": 2, "name": "Jane", "profile": { "email": "jane@test.com" } }
],
"total": 2
}
"""

# Direct access
* def total = response.total
* def firstUser = response.users[0]
* def firstName = response.users[0].name

# Using JsonPath with 'get'
* def userNames = get response.users[*].name
* match userNames == ['John', 'Jane']

# The '$' shortcut: equivalent and more concise
* def emails = $response.users[*].profile.email
* match emails == ['john@test.com', 'jane@test.com']

# '$' is optional inside match
* match response.users[*].id == [1, 2]

get with Index

Use karate.get() for safe access when the index may not exist. Use normal array indexing when working with known positions.

Gherkin
Feature: Safe array access

Scenario: Working with array indexes
* def users =
"""
[
{ "id": 1, "name": "John" },
{ "id": 2, "name": "Jane" },
{ "id": 3, "name": "Bob" }
]
"""

# Normal access (fails if index is missing)
* def firstUser = users[0]
* match firstUser.id == 1

# Safe access: returns null if out of range
* def missingUser = karate.get('users[10]')
* match missingUser == null

# Safe access with a default value
* def fallbackUser = karate.get('users[5]', { id: 0, name: 'Unknown' })
* match fallbackUser.name == 'Unknown'

# Extract a single value from an array of values
* def firstId = get[0] users[*].id
* match firstId == 1

JsonPath Filters

Use JsonPath predicates (?()) to filter JSON arrays by property values.

Gherkin
Feature: JsonPath filtering

Scenario: Filter product data
* def products =
"""
[
{ "id": 1, "name": "Laptop", "price": 999, "category": "electronics" },
{ "id": 2, "name": "Book", "price": 20, "category": "books" },
{ "id": 3, "name": "Phone", "price": 599, "category": "electronics" }
]
"""

# Filter by category
* def electronics = get products[?(@.category == 'electronics')]
* match electronics[*].name == ['Laptop', 'Phone']

# Filter by price
* def expensive = get products[?(@.price > 500)]
* match expensive[*].id == [1, 3]

# Extract a single field from all objects
* def names = get products[*].name
* match names == ['Laptop', 'Book', 'Phone']

Advanced Variable Operations

Variable Modification

Modify JSON objects after creation - useful for building complex payloads or updating data from API responses:

Gherkin
Feature: Variable modification

Scenario: Build request payload dynamically
* def user =
"""
{ "id": 123, "name": "John", "profile": { "email": "john@test.com" } }
"""

# Add or update fields
* set user.active = true
* set user.lastLogin = new Date().toISOString()

# Update nested properties
* set user.profile.verified = true
* set user.profile.phone = '+1-555-0123'

# Add arrays
* set user.permissions = ['read', 'write']
* set user.tags = []

# Validate changes
* match user.active == true
* match user.profile.verified == true

# Payload ready for request
* print user
When to Use
  • Building complex request payloads step by step
  • Updating data received from API responses
  • Adding conditional fields based on test logic
  • Preparing test data with dynamic values

Variable Copying

Assigning one variable to another creates a reference, meaning changes will affect both.
Use karate.toJson() to create an independent deep copy before modifying data.

Gherkin
Feature: Variable copying

Scenario: Reference vs copy behavior
* def original =
"""
{ "id": 1, "data": { "value": "test" } }
"""

# Reference assignment shares data
* def refUser = original
* set refUser.id = 999
* match original.id == 999

# Deep copy using karate.toJson()
* def base =
"""
{ "id": 1, "data": { "value": "test" } }
"""
* def copied = karate.toJson(base)
* set copied.id = 999
* match base.id == 1
Reference Trap

* def newVar = existingVar creates a reference, not a copy. Changes to newVar will modify existingVar too.

When to Use karate.toJson()
  • Creating variations from a base payload
  • Modifying API responses for reuse
  • Avoiding hidden data mutation across tests
  • Running tests in parallel with shared input

Common Gotchas

  • Variable overwrites: def replaces any existing variable with the same name
  • Reserved names: Cannot use url or request as variable names
  • Reference vs copy: Objects are passed by reference unless explicitly copied
Background Variable Scope

Variables defined in Background are reset before every Scenario. Do not expect values modified in one scenario to be visible in another scenario.

Why: Scenarios must be isolated and runnable independently, especially for parallel execution.

For one-time setup across all scenarios, use callonce instead:

Background:
* def authToken = callonce read('get-auth-token.feature')

Next Steps

Master variable management and continue with:

  • Data Types - Handle JSON, XML, and type conversions
  • Expressions - Advanced expressions and JavaScript
  • Actions - Use variables with Karate's built-in keywords