Skip to main content

CORE SYNTAX

Actions

Load files, evaluate JavaScript dynamically, and embed HTML documentation into test reports using Karate's built-in action keywords.

Reading Files

Karate's read() function loads files from your project with automatic type conversion based on file extension.

Basic File Reading

Feature: File reading operations

Scenario: Read different file types
# JSON files are auto-converted to objects
* def userData = read('user-data.json')
* def userArray = read('users-list.json')

# XML files are auto-converted to XML objects
* def configXml = read('config.xml')
* def orderXml = read('sample-order.xml')

# CSV files become JSON arrays (header row required)
* def csvUsers = read('users.csv')

# YAML files become JSON objects
* def yamlConfig = read('config.yaml')

# Text files as strings
* def template = read('email-template.txt')
* def sqlQuery = read('user-query.sql')

# JavaScript files as functions
* def utils = read('helpers.js')
* def result = utils.processData(userData)

# Binary files for uploads
* def pdfFile = read('document.pdf')
* def imageFile = read('logo.png')

Path Prefixes

Control how files are located using path prefixes:

Feature: Path prefix strategies

Scenario: Different path prefix types
# Classpath root access (recommended for shared resources)
* def commonAuth = read('classpath:auth/login.feature')
* def sharedData = read('classpath:common/test-data.json')
* def utilities = read('classpath:utils/helpers.js')

# Relative access (for feature-local resources)
* def localData = read('user-data.json')
* def schema = read('user-schema.json')

# This feature prefix (for called features)
* def helper = read('this:helper-scenario.feature')

# Absolute file paths (development only - not recommended for CI)
* def devConfig = read('file:/Users/dev/my-config.json')

# Dynamic file selection
* def env = karate.env || 'dev'
* def envConfig = read('classpath:config/' + env + '.json')
* def dataFile = read('test-data-' + env + '.json')

Path Prefix Rules

PrefixDescriptionExampleBest For
classpath:From classpath rootclasspath:auth/login.featureShared, reusable resources
this:Relative to current featurethis:helper.featureCalled features
file:Absolute file pathsfile:/tmp/output.jsonDevelopment only
(none)Relative to feature fileuser-data.jsonFeature-local resources

Read File As String

Bypass Auto-Conversion

Use karate.readAsString() to read files as raw text:

Feature: Read as string operations

Scenario: Read files without auto-conversion
# Read JSON as string (no parsing)
* def jsonString = karate.readAsString('user-data.json')
* def parsedLater = JSON.parse(jsonString)

# Read CSV as raw text
* def csvString = karate.readAsString('data.csv')
* def lines = csvString.split('\n')

# Read binary files as strings (for specific use cases)
* def configText = karate.readAsString('config.txt')

# Process template files
* def template = karate.readAsString('email-template.html')
* def processed = template.replace('{{name}}', 'John').replace('{{date}}', new Date().toDateString())

* assert jsonString.startsWith('{')
* assert lines.length > 1
* assert processed.includes('John')

Use Cases for String Reading

Feature: String reading use cases

Scenario: When to read as string
# For custom parsing logic
* def rawData = karate.readAsString('custom-format.txt')
* def customParsed = processCustomFormat(rawData)

# For template processing
* def htmlTemplate = karate.readAsString('report-template.html')
* def report = htmlTemplate.replace('{{title}}', 'Test Report').replace('{{results}}', testResults)

# For preserving exact formatting
* def query = karate.readAsString('complex-query.sql')
* def formattedQuery = query.replace('{{table}}', 'users_' + env)

# For GraphQL queries (treated as text)
* def graphqlQuery = karate.readAsString('user-query.graphql')
* def variables = { userId: 123 }

Given path 'graphql'
And request { query: graphqlQuery, variables: variables }
When method post
Then status 200

doc - HTML Templating

Use the doc keyword to embed custom HTML into Karate test reports.

Insert HTML into Reports

Feature: HTML documentation in reports

Scenario: Generate documentation with doc
# Load and process data
* url 'https://jsonplaceholder.typicode.com/users'
* method get
* status 200

# Create documentation for the API response
* doc { read: 'users-table.html' }

# Custom HTML with dynamic content
* def reportTime = new Date().toISOString()
* def userCount = response.length
* doc
"""
<div style="border: 1px solid #ccc; padding: 10px; margin: 10px 0;">
<h3>API Test Results Summary</h3>
<p><strong>Endpoint:</strong> /users</p>
<p><strong>Users Retrieved:</strong> """ + userCount + """</p>
<p><strong>Test Time:</strong> """ + reportTime + """</p>
<p><strong>Response Time:</strong> """ + responseTime + """ms</p>
<p style="color: green;"><strong>Status:</strong> Success</p>
</div>
"""

* print 'Documentation added to HTML report'

HTML Templates with Variables

Feature: HTML templates

Scenario: Use external HTML templates
# Load test data
* def users = [{ id: 1, name: 'John Doe', email: 'john@test.com', active: true }, { id: 2, name: 'Jane Smith', email: 'jane@test.com', active: false }]

# Template file uses Thymeleaf syntax to access Karate variables
# All variables defined in the scenario are available in the template
* doc { read: 'users-table.html' }

* print 'Users table added to report'

eval - Dynamic Code Execution

Use the eval keyword to execute JavaScript code dynamically at runtime.

Evaluate Dynamic JavaScript

Feature: Dynamic code evaluation

Scenario: Evaluate JavaScript expressions
* def operation = 'addition'
* def x = 10
* def y = 20

# Dynamic operation selection
* def jsCode =
"""
if (operation === 'addition') {
result = x + y;
} else if (operation === 'multiplication') {
result = x * y;
} else {
result = 0;
}
result;
"""
* eval jsCode
* match result == 30

# Dynamic variable assignment
* def dynamicVar = 'testValue'
* eval 'var ' + dynamicVar + ' = "dynamic content"'
* match testValue == 'dynamic content'

Conditional Logic with eval

Feature: Conditional evaluation

Scenario: Complex conditional logic
* def testMode = 'integration'
* def environment = 'staging'

# Build conditional configuration
* eval
"""
var config = {};

if (testMode === 'unit') {
config.timeout = 5000;
config.retries = 1;
config.mockEnabled = true;
} else if (testMode === 'integration') {
config.timeout = 30000;
config.retries = 3;
config.mockEnabled = false;
}

if (environment === 'prod') {
config.debug = false;
config.logLevel = 'WARN';
} else {
config.debug = true;
config.logLevel = 'DEBUG';
}

karate.set('testConfig', config);
"""

* match testConfig.timeout == 30000
* match testConfig.mockEnabled == false
* assert testConfig.debug == true

Advanced Usage

Dynamic File Loading

Feature: Dynamic file operations

Scenario: Load files based on conditions
* def env = karate.env || 'dev'
* def userType = 'premium'

# Load environment-specific configuration
* def config = read('classpath:config/' + env + '.json')

# Load user-type specific test data
* def testData = read('test-data-' + userType + '.json')

# Load schema for validation
* def schema = read('schemas/' + userType + '-user-schema.json')

# Combine files for complex scenarios
* def baseRequest = read('base-request.json')
* def override = read(userType + '-overrides.json')
* def finalRequest = karate.merge(baseRequest, override)
* print 'Loaded config for environment:', env
* print 'Using test data for user type:', userType

File Processing Pipeline

Feature: File processing pipeline

Scenario: Multi-step file processing
# Step 1: Load raw data
* def rawData = read('raw-user-data.csv')
* print 'Loaded', rawData.length, 'users from CSV'

# Step 2: Load transformation rules
* def transforms = read('user-transforms.js')

# Step 3: Apply transformations
* def processedUsers = karate.map(rawData, transforms.processUser)

# Step 4: Load validation schema
* def schema = read('processed-user-schema.json')

# Step 5: Validate processed data
* match processedUsers == '#[] #(schema)'

# Step 6: Generate test cases
* def testCases = processedUsers.map(function(user) {
return {
description: 'Test user ' + user.name,
request: user,
expectedStatus: user.valid ? 200 : 400
}
})

* print 'Generated', testCases.length, 'test cases'

File-Based Request Bodies

Feature: File-based requests

Scenario: Use files for request payloads
# JSON request body from file
Given url baseUrl
And path 'users'
And request read('create-user-request.json')
When method post
Then status 201

# XML request body
Given path 'soap/users'
And request read('soap-request.xml')
When soap action 'CreateUser'
Then status 200

# Binary file upload
Given path 'upload'
And request read('document.pdf')
When method put
Then status 200

# Template with embedded expressions
* def userId = 123
* def userName = 'John'
# File contains: { "id": "#(userId)", "name": "#(userName)" }
Given path 'users', userId
And request read('update-user-template.json')
When method put
Then status 200

Response Validation with Files

Feature: File-based validation

Scenario: Validate responses against files
Given url baseUrl
And path 'users', 123
When method get
Then status 200

# Validate against expected response file
And match response == read('expected-user-response.json')

# Validate structure against schema file
And match response == read('user-schema.json')

# Compare with baseline (for regression testing)
* def baseline = read('user-123-baseline.json')
* match response contains baseline

# Validate specific fields against reference data
* def referenceData = read('reference-user-data.json')
* match response.permissions == referenceData.defaultPermissions

Best Practices

  • File extensions: Determine auto-conversion behavior - .json, .xml, .csv, .yaml auto-convert, .txt reads as string
  • Path resolution: Relative paths resolve from the feature file location, use classpath: for shared resources
  • Classpath prefix: Use classpath: for resources shared across the project
  • Binary files: Read as byte arrays with no auto-conversion, perfect for file uploads
  • eval keyword: Use sparingly for dynamic logic - tests should be deterministic
  • doc templates: All Karate variables are available in HTML templates via Thymeleaf syntax

Next Steps

Continue mastering Karate features: