Examples Tables vs call read with Runtime Data in Karate Data-Driven Tests
0 reputation · 26 Jan 2023, 13:42 UTC
0 reputation · 26 Jan 2023, 13:42 UTC
When building data-driven API tests in Karate, the test matrix often depends on identifiers or tokens returned by a setup request executed during the run. The framework offers two documented paths: a Scenario Outline with an Examples: table, or a called feature invoked via call read() passing a table variable or JSON array constructed at runtime.
Examples: tables expand each row into a standalone scenario in the HTML report, making failures easy to trace, but cells can only reference variables already in scope through inline JavaScript expressions. In contrast, call read() with a runtime-built array composes naturally with callonce setup steps, allowing each row to incorporate values fetched moments earlier.
The trade-off centers on failure-reporting granularity: called features surface rows through the caller/callee hierarchy rather than as top-level outline rows, and the exact report layout and parallel worker distribution vary across runner APIs and Karate releases. Teams must decide whether the readability of precomputed Examples: rows outweighs the flexibility of generating test data on the fly.
How does your pinned Karate version render failures for called features versus expanded outline rows in the HTML report? Does the parallel scheduler distribute called-feature rows differently than Examples rows under your runner (JUnit 4, JUnit 5, or CLI)?
33275 reputation · 27 Jan 2023, 00:29 UTC
In Karate 1.4.0 (the version referenced in the research), a Scenario Outline with an Examples: table renders each row as an independent scenario node in the HTML report. A failure therefore shows the outline name together with the exact example values, making it easy to pinpoint the offending data set. When you use call read() to invoke a feature with a runtime‑built JSON array, the HTML report does **not** create separate scenario nodes; the failure appears as a step inside the caller scenario, showing the called‑feature name and the iteration index (if you expose it via karate.repeat or an each loop) but not a distinct scenario title.
call read() is a runtime step; the called feature is executed as a sub‑routine of the caller, so the reporter nests it under the caller’s scenario.With parallel execution enabled (karate.configure('parallel', true)) the JUnit 4, JUnit 5, and CLI runners distribute Outline rows across workers because each row is a separate test scenario. Rows processed inside a call read() loop stay on the same worker that invoked the caller, because the loop runs sequentially within that scenario.
outline.feature with a Scenario Outline and an Examples: table of three rows; make the second row fail an assertion.parallel=true (JUnit 5 example: mvn test -Dkarate.parallel=true) and open target/karate-reports/outline.feature.html. You should see three scenario nodes; the failed one shows the example values.caller.feature that builds a JSON array at runtime (e.g., * def data = [{id:1},{id:2},{id:3}]) and calls called.feature via call read('called.feature') data. Inside called.feature fail on the second element.caller.feature.html. You will see only one scenario node (the caller); the failure appears as a step inside the called feature, labelled with the iteration index (if you logged karate.index or similar).karate.configure('trace', true) or inspect the console logs; you will see Outline rows executed on different worker threads, while the call read() loop runs entirely on the thread that started the caller.If you are using a Karate version older than 0.9.0 or a custom runner configuration, the behavior described above may differ. Please confirm your Karate version and whether you are running with JUnit 4, JUnit 5, or the CLI so I can verify that the recommendation applies to your setup.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.