Skip to main content

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
Key Points
  • 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:

  1. karate-config.js (required)
  2. karate-config-<env>.js (if karate.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.

URL Reset Behavior

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:

  1. karate-base.js (if exists) - Framework defaults
  2. karate-config.js (required) - Main configuration
  3. karate-config-<env>.js (if karate.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;
}
CallSingle in Configuration

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:

OptionTypeDefaultDescription
enginestring'resemble'Comparison engine: resemble, ssim, or combinations
failureThresholdnumber0.0Percentage of pixels allowed to differ (0-100)
mismatchShouldPassbooleanfalsePass tests even when threshold exceeded
allowScalingbooleanfalseScale 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 }
]
}
}
Complete Image Comparison Documentation

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

ProblemCauseSolution
Config not loadedFile not found on classpathCheck file location and name
Variables undefinedConfiguration function errorsAdd error handling and logging
Environment not switchingkarate.env not setSet system property correctly
Secrets not loadingEnvironment variables missingValidate secret loading logic
Timeouts not appliedConfiguration after test startMove to karate-config.js

Next Steps

Master Karate configuration for robust test automation:

Ready to organize your test project? Explore Feature Files for best practices in test organization.