Skip to main content

ADVANCED

Conditional Logic

Implement if statements, ternary operators, and decision trees to make your Karate tests adapt dynamically to API responses and runtime conditions.

On this page:

Simple If Statements

Use inline if statements for basic conditional execution:

Gherkin
Feature: Basic if conditions

Scenario: Inline if statements
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
* if (response.id == 1) karate.log('Found user 1')
* if (response.name == null) karate.fail('Name should not be null')
Karate Discourages Heavy Conditional Logic

Tests that give different results on every run are discouraged. Use conditional logic sparingly for environment switching or handling known API variations.

Ternary Operators

Use ternary operators for concise conditional assignments:

Gherkin
Feature: Ternary operators

Scenario: Conditional assignment
* def env = karate.env || 'dev'
* def baseUrl = env == 'prod' ? 'https://jsonplaceholder.typicode.com' : 'https://httpbin.org'
* def timeout = env == 'prod' ? 10000 : 5000
* print 'Using: ', baseUrl, ' with timeout: ', timeout

Conditional Variable Assignment

Use ternary operators to set different values based on conditions:

Gherkin
Feature: Conditional assignment

Scenario: Select endpoint based on condition
* def useV2 = true
* def endpoint = useV2 ? 'users' : 'posts'
Given url 'https://jsonplaceholder.typicode.com'
And path endpoint, 1
When method get
Then status 200
* match response.username == 'Bret'

Conditional Response Handling

Handle different response scenarios with ternary operators:

Gherkin
Feature: Conditional response handling

Scenario: Handle response based on status
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
* def userName = response.name != null ? response.name : 'Unknown'
* match userName == 'Leanne Graham'

Controlling Test Flow

Using karate.abort()

Exit a scenario without marking it as failed:

Gherkin
Feature: Abort scenario

Scenario: Skip test conditionally
* def env = karate.env || 'dev'
* if (env == 'local') karate.abort()

Given url 'https://jsonplaceholder.typicode.com'
And path 'users'
When method get
Then status 200

Use karate.abort() to skip tests in specific environments or when preconditions are not met.

Using karate.fail()

Explicitly fail a test with a custom message:

Gherkin
Feature: Fail with message

Scenario: Fail with descriptive message
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
* if (response.id == null) karate.fail('User ID should not be null')
* if (response.name == '') karate.fail('User name should not be empty')
Descriptive Error Messages

Always use descriptive error messages with karate.fail() to make debugging easier in test reports. Prefer match statements for simple assertions since they provide detailed error output.

Conditional Feature Calls with karate.call()

When you need to call a feature conditionally inside an if statement, use karate.call():

Gherkin
Feature: Conditional feature execution

Scenario: Call feature only when needed
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
* if (responseStatus == 200) karate.call('process-user.feature')
call read() Not Valid in If Statements

The call read() syntax cannot be used inside if statements. Use karate.call() instead:

# WRONG - will cause syntax error
* if (condition) call read('feature.feature')

# CORRECT - use karate.call()
* if (condition) karate.call('feature.feature')

For shared scope with conditional logic, add true as the first argument:

* if (condition) karate.call(true, 'feature.feature')

Multi-line Conditional Blocks

For complex logic, use JavaScript function blocks:

Gherkin
Feature: Multi-line conditionals

Scenario: Complex conditional logic
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
* def handleResponse =
"""
function(resp) {
if (resp.id > 0) {
karate.log('Valid user ID:', resp.id);
return true;
} else {
karate.log('Invalid user ID');
return false;
}
}
"""
* def isValid = handleResponse(response)
* match isValid == true

Environment-Based Logic

Adapt tests to different environments using karate.env:

Gherkin
Feature: Environment-aware testing

Scenario: Environment-specific configuration
* def env = karate.env || 'dev'
* def config =
"""
{
"prod": { "validateStrict": true },
"staging": { "validateStrict": false },
"dev": { "validateStrict": false }
}
"""
* def settings = config[env]

Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
* if (settings.validateStrict) karate.match(response.email, '#regex .+@.+')

JSON Lookup Pattern

Use JSON objects for data-driven conditional logic instead of switch statements:

Gherkin
Feature: JSON lookup

Scenario: Data-driven branching
* def data =
"""
{
"foo": "hello",
"bar": "world"
}
"""
* def key = 'bar'
* match (data[key]) == 'world'

JSON Transforms

Transform JSON data using functional-style operations. Karate supports ES6 arrow functions and native JavaScript array methods.

Map and Filter Operations

Gherkin
Feature: Map and filter

Scenario: Karate map operation
* def fun = function(x){ return x * x }
* def list = [1, 2, 3]
* def res = karate.map(list, fun)
* match res == [1, 4, 9]

Scenario: Karate filter operation
* def fun = function(x){ return x % 2 == 0 }
* def list = [1, 2, 3, 4]
* def res = karate.filter(list, fun)
* match res == [2, 4]

Scenario: Convert array to different shape
* def before = [{ foo: 1 }, { foo: 2 }, { foo: 3 }]
* def fun = function(x){ return { bar: x.foo } }
* def after = karate.map(before, fun)
* match after == [{ bar: 1 }, { bar: 2 }, { bar: 3 }]

Karate Transform Functions

Gherkin
Feature: Karate transforms

Scenario: Using karate transform functions
# karate.mapWithKey converts primitives to objects
* def list = ['Bob', 'Wild', 'Nyan']
* def data = karate.mapWithKey(list, 'name')
* match data == [{ name: 'Bob' }, { name: 'Wild' }, { name: 'Nyan' }]

Scenario: filterKeys example
* def schema = { a: '#string', b: '#number', c: '#boolean' }
* def response = { a: 'x', c: true }
* match response == karate.filterKeys(schema, response)
* match karate.filterKeys(response, 'b', 'c') == { c: true }
* match karate.filterKeys(response, ['a', 'b']) == { a: 'x' }

Scenario: merge example
* def foo = { a: 1 }
* def bar = karate.merge(foo, { b: 2 })
* match bar == { a: 1, b: 2 }

ForEach Operations

Gherkin
Feature: ForEach operations

Scenario: karate.forEach() works on object key-values
* def keys = []
* def vals = []
* def idxs = []
* def fun =
"""
function(x, y, i) {
karate.appendTo(keys, x);
karate.appendTo(vals, y);
karate.appendTo(idxs, i);
}
"""
* def map = { a: 2, b: 4, c: 6 }
* karate.forEach(map, fun)
* match keys == ['a', 'b', 'c']
* match vals == [2, 4, 6]
* match idxs == [0, 1, 2]

Loops and Data Generation

Generate test data using karate.repeat() and karate.range():

Gherkin
Feature: Data generation

Scenario: Generate data with karate.repeat
* def fun = function(i){ return i * 2 }
* def foo = karate.repeat(5, fun)
* match foo == [0, 2, 4, 6, 8]

Scenario: Generate test data
* def fun = function(i){ return { name: 'User ' + (i + 1) } }
* def foo = karate.repeat(3, fun)
* match foo == [{ name: 'User 1' }, { name: 'User 2' }, { name: 'User 3' }]

Scenario: Generate range of numbers
* def foo = karate.range(4, 9)
* match foo == [4, 5, 6, 7, 8, 9]
Avoid JavaScript For Loops

Use karate.repeat() instead of JavaScript for loops to keep code concise and readable.

Sorting and Deduplication

Gherkin
Feature: Sort and dedupe

Scenario: Sort by nested property
* def foo = [{a: { b: 3 }}, {a: { b: 1 }}, {a: { b: 2 }}]
* def fun = function(x){ return x.a.b }
* def bar = karate.sort(foo, fun)
* match bar == [{a: { b: 1 }}, {a: { b: 2 }}, {a: { b: 3 }}]
* match bar.reverse() == [{a: { b: 3 }}, {a: { b: 2 }}, {a: { b: 1 }}]

Scenario: Remove duplicates
* def numbers = [1, 2, 2, 3, 3, 3, 4]
* def unique = karate.distinct(numbers)
* match unique == [1, 2, 3, 4]

Switch-Case Pattern

Implement switch-case patterns with JavaScript functions:

Gherkin
Feature: Switch-case pattern

Scenario: Handle multiple cases
* def handleStatus =
"""
function(status) {
switch(status) {
case 'pending': return { action: 'wait' };
case 'processing': return { action: 'poll' };
case 'completed': return { action: 'validate' };
case 'failed': return { action: 'retry' };
default: return { action: 'unknown' };
}
}
"""

Given url 'https://jsonplaceholder.typicode.com'
And path 'posts', 1
When method get
Then status 200
* def decision = handleStatus('completed')
* match decision.action == 'validate'

Common Patterns Reference

PatternUse CaseExample
Inline ifSingle statement* if (status == 404) karate.abort()
TernaryConditional assignment* def url = env == 'prod' ? prodUrl : devUrl
JSON lookupData-driven branching* def val = config[key]
karate.abort()Skip without failing* if (env == 'local') karate.abort()
karate.fail()Fail with message* if (!valid) karate.fail('Invalid data')
karate.call()Conditional feature call* if (cond) karate.call('feature.feature')

Next Steps