ADVANCED
Hooks and Lifecycle
Control test initialization, cleanup, and resource management using Karate's lifecycle hooks without requiring Java code.
On this page:
- Background - Run setup before every scenario
- callonce - Execute expensive setup once per feature
- karate.callSingle() - Run setup once globally, even in parallel
- afterScenario - Cleanup after each scenario
- afterFeature - Cleanup after all scenarios in a feature
- karate-config.js - Global configuration before every scenario
Hook Types Overview
| Hook | When It Runs | Scope |
|---|---|---|
karate-config.js | Before every Scenario | Global |
Background | Before every Scenario in Feature | Feature |
callonce in Background | Once per Feature | Feature |
karate.callSingle() | Once globally (thread-safe) | Global |
configure afterScenario | After every Scenario | Scenario |
configure afterFeature | After all Scenarios in Feature | Feature |
Background Setup
Use Background to run setup before every scenario in a feature:
Feature: User API tests
Background:
* url 'https://jsonplaceholder.typicode.com'
* def authToken = 'Bearer abc123'
* header Authorization = authToken
Scenario: Get user
Given path 'users', 1
When method get
Then status 200
Scenario: Get all users
Given path 'users'
When method get
Then status 200
And match response == '#[10]'
The Background runs before each scenario, ensuring consistent setup.
One-Time Feature Setup
Use callonce to execute expensive operations once per feature:
Feature: API tests with authentication
Background:
# Runs once per feature, cached for all scenarios
* def authData = callonce read('classpath:auth/login.feature')
* def token = authData.token
* url 'https://jsonplaceholder.typicode.com'
* header Authorization = 'Bearer ' + token
Scenario: First test
Given path 'users'
When method get
Then status 200
Scenario: Second test
Given path 'posts'
When method get
Then status 200
callexecutes every time it's encounteredcallonceexecutes once and caches the result for all scenarios in the feature
After Scenario Hook
Execute cleanup logic after each scenario:
Feature: After scenario cleanup
Background:
* configure afterScenario =
"""
function() {
karate.log('Scenario completed:', karate.scenario.name);
if (karate.info.errorMessage) {
karate.log('FAILED:', karate.info.errorMessage);
}
}
"""
Scenario: Test user endpoint
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
Available Properties in Hooks
Access scenario information within hooks:
| Property | Description |
|---|---|
karate.scenario.name | Current scenario name |
karate.info.errorMessage | Error message if scenario failed (null if passed) |
karate.info.scenarioType | Type: Scenario or Scenario Outline |
After Feature Hook
Configure feature-level cleanup after all scenarios complete:
Feature: After feature cleanup
Background:
* configure afterFeature =
"""
function() {
karate.log('All scenarios in feature completed');
}
"""
Scenario: First scenario
* def result = 1 + 1
* match result == 2
Scenario: Second scenario
* def result = 2 + 2
* match result == 4
The afterFeature hook only works with the Runner API for parallel execution, not the JUnit runner.
// Required for afterFeature hooks to work
Results results = Runner.path("classpath:features").parallel(5);
After Scenario Outline Hook
Handle cleanup after all rows of a data-driven test complete:
Feature: Scenario Outline hooks
Background:
* configure afterScenario =
"""
function() {
karate.log('Row completed');
}
"""
* configure afterScenarioOutline =
"""
function() {
karate.log('All rows completed');
}
"""
Scenario Outline: Validate users
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', <id>
When method get
Then status 200
Examples:
| id |
| 1 |
| 2 |
| 3 |
afterScenarioruns after each Examples rowafterScenarioOutlineruns once after all rows complete
Configuration File
karate-config.js
Configure global settings in karate-config.js (processed before every scenario):
function fn() {
var env = karate.env || 'dev';
karate.log('Running in environment:', env);
var config = {
baseUrl: 'https://jsonplaceholder.typicode.com'
};
if (env === 'prod') {
config.baseUrl = 'https://api.production.com';
}
// Set timeouts globally
karate.configure('connectTimeout', 5000);
karate.configure('readTimeout', 5000);
return config;
}
Variables returned in config are available to all scenarios.
Environment-Specific Config
Create karate-config-<env>.js files to override settings per environment:
function fn() {
return {
baseUrl: 'http://localhost:8080',
debugMode: true
};
}
Run with: -Dkarate.env=dev
Global One-Time Setup
Use karate.callSingle() for initialization that runs once globally, even across parallel threads:
function fn() {
var config = {
baseUrl: 'https://jsonplaceholder.typicode.com'
};
// Runs once globally, even in parallel execution
var auth = karate.callSingle('classpath:auth/get-token.feature');
config.authToken = auth.token;
return config;
}
callonceruns once per featurekarate.callSingle()runs once globally across all features, even in parallel
Multiple Cache Keys
Use different cache keys for different setups:
function fn() {
var config = {};
// Different cache keys create separate cached results
var adminAuth = karate.callSingle('classpath:auth.feature?admin', {
username: 'admin',
password: 'admin123'
});
var userAuth = karate.callSingle('classpath:auth.feature?user', {
username: 'testuser',
password: 'user123'
});
config.adminToken = adminAuth.token;
config.userToken = userAuth.token;
return config;
}
The ?admin and ?user suffixes create separate cache entries.
Development Mode Caching
Cache authentication tokens to disk for faster development cycles:
function fn() {
var config = {};
// Enable disk caching in dev mode
if (karate.env === 'dev') {
karate.configure('callSingleCache', { minutes: 15, dir: 'target/auth-cache' });
}
// This result will be cached to disk in dev mode
var auth = karate.callSingle('classpath:expensive-auth.feature');
config.authToken = auth.token;
return config;
}
karate.callSingle() caching requires pure JSON return values. Avoid returning JavaScript functions or Java objects - they cause caching issues in parallel execution.
Hook Summary Table
| To Run Code | How |
|---|---|
| Before everything (globally once) | karate.callSingle() in karate-config.js |
| Before every Scenario | Background section or karate-config.js |
| Once per Feature | callonce in Background |
| After every Scenario | configure afterScenario |
| After every Scenario Outline | configure afterScenarioOutline |
| After all Scenarios in Feature | configure afterFeature (requires Runner API) |
Next Steps
- Configuration - Environment setup details
- Calling Features - Reuse features and functions
- Parallel Execution - Run tests concurrently
- Debugging - Troubleshoot test failures