Skip to main content

REUSABILITY

Dynamic Scenarios

Generate test scenarios dynamically at runtime using JSON arrays, CSV files, or custom generator functions. Dynamic Scenario Outline resolves test data at execution time from files, databases, or APIs—enabling scalable data-driven testing without memory overhead.

On this page:

Simple JSON Data Source

Load test data from a JSON file at runtime. The key pattern is a single-cell Examples table that triggers dynamic resolution:

Gherkin
Feature: Dynamic data from JSON

Scenario Outline: Create user: <name>
Given url 'https://jsonplaceholder.typicode.com'
And path 'users'
And request { name: '<name>', email: '<email>' }
When method post
Then status 201

# Single-cell table triggers dynamic resolution
Examples:
| read('classpath:test-data/users.json') |
Single-Cell Pattern

Dynamic Scenario Outline requires exactly one row and one column in the Examples table. This signals Karate to resolve the data at runtime instead of using a static table.

CSV File Data Source

Use CSV files for tabular test data. Karate auto-converts CSV to JSON arrays:

Gherkin
Feature: CSV-driven tests

Scenario Outline: Test product: <name>
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
And request { title: '<name>', body: '<description>', userId: 1 }
When method post
Then status 201

Examples:
| read('classpath:test-data/products.csv') |

@setup Tag for Data Generation

Generate test data programmatically before running scenarios. The @setup tag marks a scenario that runs first and provides data via karate.setup():

Gherkin
Feature: Setup tag for dynamic data

@setup
Scenario: Generate test data
* def testPosts =
"""
[
{ title: 'First Post', body: 'Content 1', userId: 1 },
{ title: 'Second Post', body: 'Content 2', userId: 1 },
{ title: 'Third Post', body: 'Content 3', userId: 2 }
]
"""

Scenario Outline: Create post: <title>
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
And request { title: '<title>', body: '<body>', userId: <userId> }
When method post
Then status 201
And match response.title == '<title>'

Examples:
| karate.setup().testPosts |
@setup Behavior
  • @setup scenarios run before Background and all other scenarios
  • Cannot depend on Background variables
  • Access setup data using karate.setup() in the Examples table
  • Use karate.setupOnce() to run setup only once per feature

Generator Functions

Simple Generator

Create large datasets without loading all data into memory. A generator function returns null to signal the end:

Gherkin
Feature: Memory-efficient generator

@setup
Scenario: Setup generator function
* def postGenerator =
"""
function(index) {
if (index >= 10) return null;
return {
title: 'Post ' + index,
body: 'Body content for post ' + index,
userId: (index % 3) + 1
};
}
"""

Scenario Outline: Create post: <title>
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
And request { title: '<title>', body: '<body>', userId: <userId> }
When method post
Then status 201

Examples:
| karate.setup().postGenerator |

Generator with Conditional Logic

Add computed fields or conditional values based on the index. The generator can include any logic to vary test data across iterations:

Gherkin
Feature: Generator with conditions

@setup
Scenario: Complex generator
* def generator =
"""
function(index) {
if (index >= 20) return null;
return {
title: 'TestPost' + index,
userId: (index % 5) + 1,
shouldSucceed: index % 4 != 0
};
}
"""

Scenario Outline: Post test <index> - <title>
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
And request { title: '<title>', userId: <userId> }
When method post
Then status 201

Examples:
| karate.setup().generator |

Advanced Patterns

Named Setup Scenarios

When a feature has multiple Scenario Outlines that need different data sources, use named setups with @setup=name syntax. Reference specific setups using karate.setup('name'):

Gherkin
Feature: Named setup scenarios

@setup=users
Scenario: Setup user data
* def users =
"""
[
{ id: 1, name: 'Admin' },
{ id: 2, name: 'User' }
]
"""

@setup=posts
Scenario: Setup post data
* def posts =
"""
[
{ id: 101, title: 'First' },
{ id: 102, title: 'Second' }
]
"""

Scenario Outline: Test user: <name>
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', <id>
When method get
Then status 200

Examples:
| karate.setup('users').users |

Setup Once Pattern

When multiple Scenario Outlines share the same data source, use karate.setupOnce() to execute the setup scenario only once. The data is cached and reused across all outlines:

Gherkin
Feature: Setup once pattern

@setup
Scenario: Generate shared data
* def sharedData =
"""
[
{ postId: 1, commentBody: 'Great post!' },
{ postId: 1, commentBody: 'Thanks for sharing' }
]
"""

Scenario Outline: Add comment to post <postId>
Given url 'https://jsonplaceholder.typicode.com'
And path 'comments'
And request { postId: <postId>, body: '<commentBody>', email: 'test@test.com' }
When method post
Then status 201

Examples:
| karate.setupOnce().sharedData |

Building Test Matrix

Generate all combinations of multiple variables using nested loops. Useful for testing features across user types, environments, or configurations:

Gherkin
Feature: Test matrix generation

@setup
Scenario: Create test matrix
* def users = [1, 2, 3]
* def postTypes = ['text', 'image']
* def testMatrix = []
* karate.forEach(users, function(userId) { karate.forEach(postTypes, function(type) { testMatrix.push({ userId: userId, postType: type, title: type + ' post by user ' + userId }) }) })

Scenario Outline: Create <postType> post for user <userId>
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
And request { title: '<title>', body: 'Content', userId: <userId> }
When method post
Then status 201

Examples:
| karate.setup().testMatrix |

Database-Driven Tests

Query test data directly from a database using Java interop. The setup scenario executes the query and returns rows as a JSON array for the Scenario Outline:

Gherkin
Feature: Database-driven tests

@setup
Scenario: Load from database
* def DbUtils = Java.type('com.mycompany.DbUtils')
* def dbConfig = { url: 'jdbc:h2:mem:test', user: 'sa' }
* def query = 'SELECT user_id, username FROM test_users WHERE active = true'
* def testUsers = DbUtils.readRows(dbConfig, query)

Scenario Outline: Test user - <username>
Given url baseUrl
And path 'user/profile'
And request { userId: <user_id> }
When method get
Then status 200

Examples:
| karate.setup().testUsers |

When to Use Dynamic Scenarios

Use CaseApproach
Fixed, small dataset (< 20 rows)Static Examples table
Runtime data (API, database, files)Dynamic Scenario Outline
Large datasets (100+ test cases)Generator functions
Environment-specific test generation@setup with conditional logic

Next Steps