Data-Driven Testing
Run the same test once per row of tabular data. Both runners support this with slightly different syntax.
v2 (kis test): data: + table:
Section titled “v2 (kis test): data: + table:”Declare named data sources at the suite level, reference one from a test:
# suite.yaml (or the test file of a single-file suite)data: users: type: csv file: fixtures/users.csv # relative to the declaring suite's directory scopes: type: inline rows: - { name: full, scope: "read write" } - { name: readonly, scope: "read" }
tests: - name: get-user table: users # once per CSV row steps: - name: fetch http: url: "{{baseurl}}/users/{{id}}" method: GET assertions: - status_code == 200 - response.name == "{{name}}"Source types
Section titled “Source types”type | Source | Notes |
|---|---|---|
inline | rows: — a YAML list of maps | no file needed |
yaml / yml | file: | top-level list of maps, or { rows: [...] } |
json | file: | same shapes as yaml |
csv | file: | first row = header; all values are strings; leading space trimmed; ragged rows are an error |
Semantics
Section titled “Semantics”file:paths resolve relative to the directory of the suite that declares the source.- Lookup walks the suite tree leaf → root, so a parent suite can declare tables for all its descendants.
- Rows lazy-load on first use and are cached for the run.
- Each row clones the test; row fields override
test.variables(and anything below them in the scope precedence). - Per-iteration result names take a suffix from the first present of:
_namecolumn →namecolumn →idcolumn →[row=N]. - Iteration is sequential and stops at the first failed row unless the test sets
continue_on_error: true. - A
table:reference that yields zero rows marks the test errored (an empty fixture is treated as a bug, not a skip). before_each/after_eachhooks run around every row.
Legacy (test.svc tests): tables: + table:
Section titled “Legacy (test.svc tests): tables: + table:”File-level tables: with per-step (or per-testcase) table: references:
tables: users: type: csv file: users.csv # relative to the suite directory
steps: - name: get-user-by-id table: users rest: url: "{{baseurl}}/users/{{id}}" method: GET- Table types:
csv(optionalseparator:, default,) andexcel(requiressheet:). - File-level
tables:propagate automatically to any step/testcase/scenario/testplan in the file that references atable:without declaring its own. - Rows show up in the summary as
-RC0,-RC1, … suffixes — only when there are ≥ 2 records; single-record runs keep clean names.
CLI data files (-d/--datapath)
Section titled “CLI data files (-d/--datapath)”The tests runner also takes data on the command line, repeatable and merged in order:
test.svc tests -p tests/data-driven -d env.json -stest.svc tests -p tests/ -d vars.yaml -d users.csv -s.json/.yamlfiles merge into the variable map (later files override earlier)..csvfiles fan out: every row becomes a separate execution record over the merged variables.-v key=valueinline vars override everything from-d.
Choosing an approach
Section titled “Choosing an approach”- Fixture-shaped inputs that belong with the tests → v2
data:/table:(checked in next to the suite, resolved relative to it). - Environment-shaped values (URLs, credentials) → env files, not tables (env-file auto-discovery).
- Quick ad-hoc parameter sweeps with the legacy runner →
-d file.csv.