CORE SYNTAX
Configuration
Configure test settings, environment-specific values, and shared utilities using JavaScript files that execute before every scenario.
Benefits of Configuration
- Environment switching: Toggle between dev, staging, and production with a single property
- Shared utilities: Define reusable functions and data generators available across all tests
- Dynamic values: Generate tokens, timestamps, and session IDs at runtime
- Global HTTP settings: Configure timeouts, SSL, proxies, and authentication once
Simple Configuration
Create a karate-config.js
file in src/test/java
that returns configuration values:
function fn() {
var config = {
baseUrl: 'https://api.example.com',
apiKey: 'my-api-key'
};
return config;
}
Access configuration variables directly in your feature files:
Feature: User API
Scenario: Get user with config
Given url baseUrl
And path 'users/1'
And header X-API-Key = apiKey
When method get
Then status 200
- Configuration executes before every scenario
- Variables defined in config are available globally
- File must be named
karate-config.js
and located on the classpath
Environment Switching
Switch between environments using the karate.env
system property:
function fn() {
var env = karate.env || 'dev';
karate.log('karate.env system property was:', env);
var config = { env: env };
if (env == 'dev') {
config.baseUrl = 'http://localhost:8080';
} else if (env == 'staging') {
config.baseUrl = 'https://staging-api.example.com';
} else if (env == 'prod') {
config.baseUrl = 'https://api.example.com';
}
return config;
}
Set the environment when running tests:
# Maven
mvn test -Dkarate.env=staging
# Gradle
./gradlew test -Dkarate.env=prod
# Standalone JAR
java -jar karate.jar -e prod tests/
Dynamic Configuration Values
Generate dynamic values during configuration:
function fn() {
var config = {
// Static values
appName: 'MyTestApp',
// Dynamic values
requestId: java.util.UUID.randomUUID() + '',
timestamp: new Date().getTime(),
// Functions for later use
generateToken: function() {
return 'token-' + java.util.UUID.randomUUID();
},
// Default headers
defaultHeaders: {
'Content-Type': 'application/json',
'X-Request-Time': new Date().toISOString()
}
};
return config;
}
Use dynamic values in your tests:
Scenario: API call with dynamic headers
* def token = generateToken()
Given url baseUrl
And path 'users'
And header Authorization = 'Bearer ' + token
And headers defaultHeaders
When method get
Then status 200
System Properties and Environment Variables
Access external configuration sources:
function fn() {
var config = {
// From system properties (-Dapi.key=value)
apiKey: karate.properties['api.key'],
// From environment variables
dbPassword: java.lang.System.getenv('DB_PASSWORD'),
secretKey: java.lang.System.getenv('SECRET_KEY'),
// From Java system properties
userHome: java.lang.System.getProperty('user.home'),
// With defaults
timeout: parseInt(karate.properties['timeout'] || '5000')
};
// Validation
if (!config.apiKey) {
throw new Error('API_KEY is required');
}
return config;
}
Pass system properties when running tests:
mvn test -Dapi.key=abc123 -Dtimeout=10000
Environment-Specific Files
Create separate configuration files for each environment:
src/test/java/
├── karate-config.js # Base configuration
├── karate-config-dev.js # Development overrides
├── karate-config-staging.js # Staging overrides
└── karate-config-prod.js # Production overrides
karate-config-dev.js:
function fn() {
var config = {
baseUrl: 'http://localhost:8080',
debugMode: true,
mockExternalServices: true
};
// Development-specific settings
karate.configure('logPrettyRequest', true);
karate.configure('logPrettyResponse', true);
return config;
}
karate-config-prod.js:
function fn() {
var config = {
baseUrl: 'https://api.production.com',
debugMode: false,
// Load credentials from environment
credentials: {
apiKey: java.lang.System.getenv('PROD_API_KEY'),
clientSecret: java.lang.System.getenv('PROD_CLIENT_SECRET')
}
};
// Validate production requirements
if (!config.credentials.apiKey) {
throw new Error('PROD_API_KEY environment variable is required');
}
// Production settings
karate.configure('ssl', true);
return config;
}
Configuration files are loaded in this order:
karate-config.js
(required)karate-config-<env>.js
(ifkarate.env
is set)
HTTP Client Configuration
Configure global HTTP client behavior:
function fn() {
var env = karate.env || 'dev';
// Timeouts
karate.configure('connectTimeout', 5000);
karate.configure('readTimeout', 30000);
// SSL validation
karate.configure('ssl', env !== 'dev');
// Follow redirects
karate.configure('followRedirects', true);
// Retry configuration
karate.configure('retry', {
count: 3,
interval: 1000
});
return { env: env };
}
Configure URL Persistence
Persist the base URL across feature calls:
Feature: URL persistence
Scenario: Main test
* configure url = 'https://api.example.com'
* path 'users'
* method get
* call read('helper.feature')
@ignore
Scenario: Helper feature
# URL is inherited, no need to set again
* path 'orders'
* method get
The configure url
setting ensures the base URL persists when calling other features, eliminating the need to reset it in every scenario.
The url
keyword resets after each HTTP request by default. Use configure url
to maintain the base URL across multiple feature invocations.
NTLM Authentication
Configure Windows domain authentication for corporate environments:
Scenario: NTLM authentication
* configure ntlmAuth = {
username: 'admin',
password: 'secret',
domain: 'CORPORATE',
workstation: 'BUILD-01'
}
* url 'https://corporate-api.example.com'
* path 'protected'
* method get
* status 200
Minimal credentials (without domain/workstation):
Scenario: NTLM with credentials only
* configure ntlmAuth = {
username: 'admin',
password: 'secret'
}
* url 'https://internal-api.example.com'
* method get
In karate-config.js:
function fn() {
var env = karate.env || 'dev';
if (env === 'corporate') {
karate.configure('ntlmAuth', {
username: karate.properties['ntlm.user'],
password: java.lang.System.getenv('NTLM_PASSWORD'),
domain: 'CORPORATE',
workstation: 'BUILD-SERVER'
});
}
return {};
}
SSL and Proxy Configuration
Configure SSL validation and corporate proxy settings:
function fn() {
var env = karate.env || 'dev';
// SSL validation
karate.configure('ssl', env !== 'dev');
// Simple proxy
if (env === 'corporate') {
karate.configure('proxy', 'http://proxy.company.com:8080');
}
// Proxy with authentication
if (env === 'secure-proxy') {
karate.configure('proxy', {
uri: 'http://proxy.company.com:8080',
username: 'proxyuser',
password: 'proxypass'
});
}
return {};
}
Logging Configuration
Configure logging based on environment:
function fn() {
var env = karate.env || 'dev';
if (env === 'dev') {
karate.configure('logPrettyRequest', true);
karate.configure('logPrettyResponse', true);
karate.configure('printEnabled', true);
} else if (env === 'prod') {
karate.configure('logPrettyRequest', false);
karate.configure('logPrettyResponse', false);
karate.configure('printEnabled', false);
}
return { environment: env };
}
Advanced: karate-base.js
For teams building frameworks on top of Karate, create karate-base.js
with shared utilities:
function fn() {
var config = {
// Common utilities
utils: {
generateId: function() {
return 'ID-' + java.util.UUID.randomUUID();
},
today: function() {
return new java.text.SimpleDateFormat('yyyy-MM-dd')
.format(new java.util.Date());
},
isValidEmail: function(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
},
// Authentication helpers
auth: {
basic: function(username, password) {
var credentials = username + ':' + password;
var encoded = java.util.Base64.getEncoder()
.encodeToString(credentials.getBytes());
return 'Basic ' + encoded;
},
bearer: function(token) {
return 'Bearer ' + token;
}
}
};
return config;
}
karate-config.js extends karate-base.js:
function fn() {
// Access framework configuration
var frameworkConfig = karate.get('config') || {};
var config = karate.merge(frameworkConfig, {
projectName: 'MyAPITests',
baseUrl: 'https://api.example.com',
// Use framework utilities
projectUtils: {
createTestOrder: function() {
return {
orderId: frameworkConfig.utils.generateId(),
created: frameworkConfig.utils.today()
};
}
}
});
return config;
}
Configuration files are loaded in this order:
karate-base.js
(if exists) - Framework defaultskarate-config.js
(required) - Main configurationkarate-config-<env>.js
(ifkarate.env
is set) - Environment overrides
Advanced: Modular Configuration
Load configuration from separate JSON files:
function fn() {
var env = karate.env || 'dev';
var loadConfig = function(configName) {
try {
var configFile = karate.read('classpath:config/' + configName + '.json');
return configFile[env] || configFile.default || {};
} catch (e) {
karate.log('Config file not found:', configName);
return {};
}
};
var config = {
env: env,
database: loadConfig('database'),
services: loadConfig('services'),
features: loadConfig('features')
};
return config;
}
config/services.json:
{
"default": {
"userService": "http://localhost:8080",
"paymentService": "http://localhost:8081"
},
"staging": {
"userService": "https://user-service.staging.com",
"paymentService": "https://payment-service.staging.com"
},
"prod": {
"userService": "https://user-service.prod.com",
"paymentService": "https://payment-service.prod.com"
}
}
Advanced: Secure Configuration
Load secrets securely based on environment:
function fn() {
var env = karate.env || 'dev';
var loadSecrets = function() {
if (env === 'local') {
// Load from local file (not in version control)
try {
return karate.read('classpath:local-secrets.properties');
} catch (e) {
return { apiKey: 'dev-api-key' };
}
} else {
// Load from environment variables
return {
apiKey: java.lang.System.getenv('API_KEY'),
dbPassword: java.lang.System.getenv('DB_PASSWORD')
};
}
};
var secrets = loadSecrets();
// Validate required secrets
if (!secrets.apiKey) {
throw new Error('API_KEY is required for environment: ' + env);
}
return {
env: env,
credentials: secrets
};
}
Advanced: One-Time Initialization
Use karate.callSingle()
for expensive initialization:
function fn() {
var env = karate.env || 'dev';
// One-time setup (runs once per test execution)
var oneTimeSetup = karate.callSingle('classpath:setup/one-time-setup.feature');
var config = {
env: env,
globalToken: oneTimeSetup.globalToken,
sharedData: oneTimeSetup.sharedData
};
// Configure based on setup results
if (config.globalToken) {
karate.configure('headers', {
Authorization: 'Bearer ' + config.globalToken
});
}
return config;
}
When using karate.callSingle()
in karate-config.js
, return only simple data types (JSON objects, strings, numbers). Avoid returning Java objects or JavaScript functions, as they may not serialize correctly across parallel threads.
See Calling Features for more details.
Image Comparison Configuration
Configure visual regression testing behavior:
Scenario: Image comparison setup
* configure imageComparison = {
engine: 'resemble',
failureThreshold: 2,
mismatchShouldPass: false
}
* compareImage {
baseline: 'screenshots/login.png',
latest: '#(currentScreenshot)'
}
Configuration options:
Option | Type | Default | Description |
---|---|---|---|
engine | string | 'resemble' | Comparison engine: resemble , ssim , or combinations |
failureThreshold | number | 0.0 | Percentage of pixels allowed to differ (0-100) |
mismatchShouldPass | boolean | false | Pass tests even when threshold exceeded |
allowScaling | boolean | false | Scale images to match dimensions |
Ignore dynamic areas:
Scenario: Ignore header and timestamp
* compareImage {
baseline: 'page.png',
latest: '#(screenshot)',
options: {
ignoredBoxes: [
{ x: 0, y: 0, width: 1920, height: 60 },
{ x: 1600, y: 900, width: 320, height: 100 }
]
}
}
For detailed image comparison documentation including visual validation workflows, see Image Comparison.
Configuration Debugging
Debug configuration loading with logging:
function fn() {
karate.log('=== Configuration Debug Info ===');
karate.log('karate.env:', karate.env);
karate.log('user.dir:', java.lang.System.getProperty('user.dir'));
var config = {
debug: true,
systemInfo: {
javaVersion: java.lang.System.getProperty('java.version'),
osName: java.lang.System.getProperty('os.name')
}
};
karate.log('Final configuration:', config);
return config;
}
Validate configuration in tests:
Feature: Configuration validation
Scenario: Verify configuration completeness
# Print configuration
* print 'Environment:', env
* print 'Base URL:', baseUrl
# Validate required values
* assert baseUrl != null
* assert baseUrl.startsWith('http')
# Test connectivity
* url baseUrl + '/health'
* method get
* assert responseStatus == 200 || responseStatus == 404
Configuration Best Practices
Security
// Good: Secure credential handling
function fn() {
var env = karate.env || 'dev';
var config = {
apiKey: java.lang.System.getenv('API_KEY') ||
karate.properties['api.key'] ||
(env === 'dev' ? 'dev-api-key' : null)
};
if (!config.apiKey) {
throw new Error('API key configuration required');
}
return config;
}
// Avoid: Hardcoded secrets
function fn() {
return {
apiKey: 'hardcoded-secret-key', // Security risk!
dbPassword: 'admin123' // Never do this!
};
}
Environment Management
// Good: Environment-aware configuration
function fn() {
var env = karate.env || 'dev';
var environments = {
dev: {
baseUrl: 'http://localhost:8080',
features: { mockMode: true, debugMode: true }
},
prod: {
baseUrl: 'https://api.example.com',
features: { mockMode: false, debugMode: false }
}
};
var config = environments[env];
if (!config) {
throw new Error('Unknown environment: ' + env);
}
config.env = env;
return config;
}
Validation
// Good: Comprehensive validation
function fn() {
var config = {
baseUrl: karate.properties['base.url'] || 'http://localhost:8080',
timeout: parseInt(karate.properties['timeout'] || '5000')
};
// Validation rules
if (!config.baseUrl) {
throw new Error('baseUrl is required');
}
if (config.timeout <= 0) {
throw new Error('timeout must be positive');
}
if (!config.baseUrl.startsWith('http')) {
throw new Error('baseUrl must be a valid URL');
}
return config;
}
Troubleshooting
Problem | Cause | Solution |
---|---|---|
Config not loaded | File not found on classpath | Check file location and name |
Variables undefined | Configuration function errors | Add error handling and logging |
Environment not switching | karate.env not set | Set system property correctly |
Secrets not loading | Environment variables missing | Validate secret loading logic |
Timeouts not applied | Configuration after test start | Move to karate-config.js |
Next Steps
Master Karate configuration for robust test automation:
- Organize configuration files effectively: Feature Files
- Use callSingle for one-time setup: Calling Features
- Configure lifecycle hooks: Hooks
- Set up parallel execution: Parallel Execution
- Configure visual testing: Image Comparison
Ready to organize your test project? Explore Feature Files for best practices in test organization.