Skip to main content

Step Reference

Complete catalogue of every KTestify step. All DataTable columns are listed with their type, whether they are required, the default value (if any), and an inline example.


Background: Given steps​

Given namespace​

Declares a single namespace prefix applied to all topic names.

Given namespace
| namespace |
| myapp |
ColumnTypeRequiredDefaultDescription
namespacestring✅noneNamespace prefix (e.g. myapp, com.example)

Given namespaces​

Declares multiple named namespace prefixes.

Given namespaces
| namespace | namespaceAlias |
| myapp.input | input-ns |
| myapp.audit | audit-ns |
ColumnTypeRequiredDefaultDescription
namespacestring✅noneNamespace prefix
namespaceAliasstring✅noneAlias referenced in topic declarations

Given input topic​

Declares one or more Kafka topics as producers (INPUT type).

Given input topic
| topicName | topicAlias | namespace | namespaceAlias |
| orders-in | orders-in | | |
ColumnTypeRequiredDefaultDescription
topicNamestring✅nonePhysical topic name (namespace prepended)
topicAliasstring✅noneAlias for use in When steps
namespacestring❌Config defaultOverride namespace for this topic
namespaceAliasstring❌noneReference a Given namespaces alias

Given output topic​

Declares one or more Kafka topics as consumers (OUTPUT type).

Given output topic
| topicName | topicAlias | namespace | namespaceAlias |
| orders-out | enriched | myapp | |
ColumnTypeRequiredDefaultDescription
topicNamestring✅nonePhysical topic name (namespace prepended)
topicAliasstring✅noneAlias for use in Then steps
namespacestring❌Config defaultOverride namespace for this topic
namespaceAliasstring❌noneReference a Given namespaces alias

Given assets directory​

Sets the base directory for all relative file paths in the scenario.

Given assets directory
| absolutePath |
| src/test/resources/assets |
ColumnTypeRequiredDefaultDescription
absolutePathstring✅KTESTIFY_ASSETS_DIR / configAbsolute or project-relative path

Given schema​

Declares an Avro schema for use in Avro producer/consumer steps.

Given schema
| schemaName | schemaAlias | schemaVersion |
| Order | order | 1 |
ColumnTypeRequiredDefaultDescription
schemaNamestring✅noneSchema Registry subject name (prefix for schemaName-value)
schemaAliasstring✅noneShort alias
schemaVersioninteger❌latestSchema version to use

Actions: When steps​

Multi-row DataTables

Producer and script steps below accept multiple DataTable rows, executed sequentially in order. Producer steps additionally require every row to resolve to the same physical topic (TopicMismatchException otherwise). See Multi-row DataTables for full details.

When record from file is sent​

Produces a raw String message to a Kafka input topic.

When record from file is sent
| topicName | file | recordKey | headerFile |
| orders-in | payload.json | key-001 | headers.json |
ColumnTypeRequiredDefaultDescription
topicNamestring✅noneTopic name or alias (must be declared as INPUT)
filestring✅nonePayload file, relative to assets directory
recordKeystring❌nullKafka record key
headerFilestring❌noneJSON file of Kafka headers {"name":"value"}

When record from file based on schema is sent​

Produces an Avro-serialised message.

When record from file based on schema is sent
| topicName | file | schemaName | recordKey |
| orders-in | order.json | Order | ord-001 |
ColumnTypeRequiredDefaultDescription
topicNamestring✅noneInput topic name or alias
filestring✅noneJSON payload file
schemaNamestring❌TopicNameStrategySchema alias or name declared via Given schema
recordKeystring❌nullKafka record key

And wait for {int} seconds​

Pauses execution.

And wait for 5 seconds
ParameterTypeRequiredDescription
{int}integer✅Seconds to pause

When script is executed / And execute script​

Runs a shell script.

When script is executed
| scriptPath | scriptArgs |
| ./scripts/reset.sh | arg1,arg2 |
ColumnTypeRequiredDefaultDescription
scriptPathstring✅nonePath to the script file
scriptArgsstring❌noneComma-separated arguments

Fails if exit code ≠ 0.


Assertions: Then / And steps​

Multi-row DataTables

Every single-record assertion step below (all except the two batch steps) accepts multiple DataTable rows, validated sequentially in order, provided every row targets the same physical topic (TopicMismatchException otherwise). All rows in the same step share one pinned referenceTimestamp so delta-time seek windows don't drift row-to-row. The batch steps (expected records from files / ...based on schema) remain strictly single-row. See Multi-row DataTables → for full details.

Then expected record from file​

Raw file match, full value equality.

Then expected record from file
| topicAlias | file | expectedRecordKey | keyMatchStrategy | consumerReadTimeout | consumerDeltaTime |
| orders-out | expected.json | key-001 | exact | 30 | 60 |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
filestring✅noneExpected file path
expectedRecordKeystring❌noneFilter by record key
keyMatchStrategystring❌exactKey matching strategy: exact, contains, starts_with, ends_with, regex
consumerReadTimeoutinteger❌Config (30)Seconds to wait
consumerDeltaTimeinteger❌Config (60)Seconds to seek back

Then expected record should have fields matching from file​

Positional character field match.

Then expected record should have fields matching from file
| topicAlias | file | line | from | to |
| orders-out | expected.txt | 2 | 0 | 15 |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
filestring✅noneExpected file
lineinteger✅none1-based line number
frominteger✅noneStart char index (inclusive)
tointeger✅noneEnd char index (exclusive)

Then expected record from file based on XML​

Structural XML comparison with optional element exclusions.

Then expected record from file based on XML
| topicAlias | file | excludedElements | expectedRecordKey | keyMatchStrategy |
| orders-out | expected.xml | ns:CreationDateTime | | |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
filestring✅noneExpected XML file
excludedElementsstring❌noneComma-separated element names to skip
expectedRecordKeystring❌noneFilter by record key
keyMatchStrategystring❌exactKey matching strategy: exact, contains, starts_with, ends_with, regex
consumerReadTimeoutinteger❌Config (30)Seconds to wait
consumerDeltaTimeinteger❌Config (60)Seconds to seek back

Then expected record based on XML should have fields matching from file​

XPath extraction + comparison.

Then expected record based on XML should have fields matching from file
| topicAlias | file | xpathExpressions |
| orders-out | expected.txt | //Weight[@unit='KG']/text(),//Sender/ID/text() |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
filestring✅noneExpected values file (one per line)
xpathExpressionsstring✅noneComma-separated XPath expressions

Then expected record from file based on schema​

Avro → JSON file match with optional field exclusions.

Then expected record from file based on schema
| topicAlias | file | excludedKeys | expectedRecordKey | keyMatchStrategy | consumerReadTimeout |
| orders-out | expected.json | createdAt,eventId | ord-001 | exact | 30 |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
filestring✅noneExpected JSON file
excludedKeysstring❌noneComma-separated Avro field names to exclude
expectedRecordKeystring❌noneFilter by record key
keyMatchStrategystring❌exactKey matching strategy: exact, contains, starts_with, ends_with, regex
consumerReadTimeoutinteger❌Config (30)Seconds to wait
consumerDeltaTimeinteger❌Config (60)Seconds to seek back

Then expected record based on schema should have fields matching from given value​

Assert specific Avro field values without a file.

Single field (use key / value columns):

Then expected record based on schema should have fields matching from given value
| topicAlias | key | value |
| orders-out | status | PROCESSED |

Multiple fields (use keys / values columns, semicolon-separated):

Then expected record based on schema should have fields matching from given value
| topicAlias | keys | values |
| orders-out | status;amount | PENDING;99 |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
keystring❌*noneAvro field name (single-field mode)
valuestring❌*noneExpected field value (single-field mode)
keysstring❌*noneSemicolon-separated Avro field names (multi-field mode)
valuesstring❌*noneSemicolon-separated expected values (multi-field mode)
consumerReadTimeoutinteger❌Config (30)Seconds to wait
consumerDeltaTimeinteger❌Config (60)Seconds to seek back

* Either key + value or keys + values must be provided.


Then expected records from files​

Raw batch, collect N records and match against N expected files (positionally by default, or in any order when batchMatchStrategy is lazy).

Then expected records from files
| topicAlias | expectedRecordsCount | files | batchMatchStrategy | consumerReadTimeout |
| orders-out | 3 | f1.json,f2.json,f3.json | positional | 60 |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
expectedRecordsCountinteger✅noneExact number of records to collect
filesstring✅noneComma-separated expected file paths
batchMatchStrategystring❌positionalBatch matching strategy (positional, lazy)
expectedRecordKeysstring❌noneComma-separated expected keys paired 1-to-1 with files (or a single key shared across all records in the batch), filtered during polling and asserted via batchMatchStrategy and keyMatchStrategy
expectedRecordKeystring❌noneSingle key filter applied while collecting batch records
keyMatchStrategystring❌exactKey matching strategy (exact, contains, starts_with, ends_with, regex)
consumerReadTimeoutinteger❌Config (30)Seconds to wait for all records
consumerDeltaTimeinteger❌Config (60)Seconds to seek back

Then expected records from files based on schema​

Avro batch, collect N Avro records and match against N expected files (positionally by default, or in any order when batchMatchStrategy is lazy).

Then expected records from files based on schema
| topicAlias | expectedRecordsCount | files | excludedKeys | batchMatchStrategy | consumerReadTimeout |
| orders-out | 2 | exp-1.json,exp-2.json | ts,eventId | lazy | 60 |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
expectedRecordsCountinteger✅noneExact number of records to collect
filesstring✅noneComma-separated expected JSON file paths
excludedKeysstring❌noneAvro field names to exclude from all records
batchMatchStrategystring❌positionalBatch matching strategy (positional, lazy)
expectedRecordKeysstring❌noneComma-separated expected keys paired 1-to-1 with files (or a single key shared across all records in the batch), filtered during polling and asserted via batchMatchStrategy and keyMatchStrategy
expectedRecordKeystring❌noneSingle key filter applied while collecting batch records
keyMatchStrategystring❌exactKey matching strategy (exact, contains, starts_with, ends_with, regex)
consumerReadTimeoutinteger❌Config (30)Seconds to wait for all records
consumerDeltaTimeinteger❌Config (60)Seconds to seek back

And record should appear in topic​

Positive watcher, asserts at least one record is present.

And record should appear in topic
| topicAlias | topicType | expectedRecordKey | keyMatchStrategy | consumerReadTimeout | consumerDeltaTime |
| orders-out | raw | order- | starts_with | 15 | 60 |
ColumnTypeRequiredDefaultDescription
topicAliasstring✅noneOutput topic alias
topicTypestring✅noneraw or avro
expectedRecordKeystring❌noneFilter by record key
keyMatchStrategystring❌exactKey matching strategy: exact, contains, starts_with, ends_with, regex
consumerReadTimeoutinteger❌Config (30)Seconds to wait
consumerDeltaTimeinteger❌Config (60)Seconds to seek back

And record should not appear in topic​

Negative watcher, asserts no record appears within the timeout.

And record should not appear in topic
| topicAlias | topicType | expectedRecordKey | keyMatchStrategy | consumerReadTimeout | consumerDeltaTime |
| orders-out | raw | non-existent | exact | 10 | 30 |

Same columns as record should appear in topic.


Matcher × Topic type compatibility​

Matcher stepraw topicsavro topics
expected record from file✅❌ use based on schema
expected record from file based on XML✅❌ not available
expected record based on XML / XPath✅❌ not available
expected record from file based on schema❌✅
expected record based on schema / field value❌✅
expected records from files (batch)✅❌
expected records from files based on schema (batch)❌✅
record should (not) appear in topic✅ both✅ both

Key matching strategies​

When a step includes an expectedRecordKey column, you can optionally specify a keyMatchStrategy column to control how the expected key is matched against the actual record key. This is useful when record keys are dynamically generated (UUIDs, prefixed keys, timestamps) and an exact match is too restrictive.

StrategyDataTable valueBehaviourExample
EXACTexactExact string equality (default)"order-001" matches "order-001"
CONTAINScontainsExpected key is a substring of the actual key"order" matches "order-001"
STARTS_WITHstarts_withActual key starts with the expected key"order-" matches "order-001"
ENDS_WITHends_withActual key ends with the expected key"001" matches "order-001"
REGEXregexActual key matches the expected Java regex pattern"order-\\d+" matches "order-001"
Parsing

The keyMatchStrategy value is case-insensitive and tolerant of hyphens, underscores, and spaces. For example, starts_with, starts-with, starts_with, StartsWith, and starts with all resolve to STARTS_WITH. Unrecognised values default to EXACT.

Topic isolation

When using non-exact strategies (contains, regex, starts_with), ensure your match pattern is specific enough to uniquely identify the intended record. Kafka topics may contain records from prior scenarios in the same feature file, and a broad pattern (e.g. contains "key") may match a decoy record first, causing value mismatches.

Example: matching a UUID-prefixed key​

# Record key is "550e8400-e29b-41d4-a716-446655440000"
Then expected record from file
| topicAlias | file | expectedRecordKey | keyMatchStrategy | consumerReadTimeout |
| orders-out | expected.json | 550e8400 | starts_with | 30 |

Example: matching a dynamic key with regex​

# Record key is "ORD-2026-000001"
Then expected record from file
| topicAlias | file | expectedRecordKey | keyMatchStrategy | consumerReadTimeout |
| orders-out | expected.json | ORD-\d{4}-\d{6} | regex | 30 |

Batch matching strategies​

In batch assertion steps (Then expected records from files and Then expected records from files based on schema), the optional batchMatchStrategy column controls how collected records are compared against the comma-separated list of expected files:

StrategyAccepted DataTable valuesBehaviour
POSITIONALpositional, ordered, index, strictDefault. Record at index i must match file at index i (and expectedRecordKeys[i] when set).
LAZYlazy, fuzzy, unordered, any_order, any-orderOrder-independent 1-to-1 matching without replacement. Each consumed record claims the first unmatched expected file (and corresponding expectedRecordKeys[j] when set) whose content and key match.
Parsing

The batchMatchStrategy value is case-insensitive and normalizes hyphens and spaces to underscores. Unrecognised or blank values default to POSITIONAL.

Then expected records from files
| topicAlias | expectedRecordsCount | files | batchMatchStrategy | consumerReadTimeout |
| orders-out | 3 | f1.json,f2.json,f3.json | lazy | 30 |

See also​