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
Prefix | Description | Example | Best For |
---|---|---|---|
classpath: | From classpath root | classpath:auth/login.feature | Shared, reusable resources |
this: | Relative to current feature | this:helper.feature | Called features |
file: | Absolute file paths | file:/tmp/output.json | Development only |
(none) | Relative to feature file | user-data.json | Feature-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:
- Build data-driven tests: Data-Driven Tests
- Apply file reading to API testing: HTTP Requests
- Reuse features with file operations: Reusability