Scenario Outline Parameters
Examples table values don't only fill quoted parameters. They reach every kind of step
parameter a Scenario Outline has — quoted values, doc strings and data tables alike.
How they get there differs, and that difference shows up in your step method signatures.
Source: examples/common-use-cases/example-8 on GitHub.
What this demonstrates
- A
<placeholder>filling a whole quoted value becomes a method parameter, with its type inferred - A
<placeholder>mixed with fixed text is substituted at the call site instead - A
<placeholder>inside a doc string is substituted at the call site; the parameter staysString - A
<placeholder>inside a data table cell is substituted at the call site too - A data table can mix static cells and placeholders in the same table
- A doc string may carry a content type (
"""json) without changing the Java signature
The rule
There are only two behaviours, and one question decides which you get:
Is the placeholder the entire value?
| Becomes | Signature | |
|---|---|---|
"<product>" — whole value | a typed method parameter | changes |
"ORD-<year>-<region>" — mixed with text | a replaceAll at the call site | unchanged |
| doc string content | a replaceAll at the call site | unchanged |
| data table cell | a constructor argument at the call site | unchanged |
Only the first case touches your step method. Everything else is substituted where the step is called, so the method you write never has to know an outline was involved.
Whole quoted value
The placeholder is the entire value, so it's passed straight through — and its type comes from the
Examples column, not from the quotes around it:
When I add "<product>" to the cart
Examples: Single-product orders
| product | qty | total |
| Wireless Mouse | 1 | 29.99 |
public abstract void iAdd$p1ToTheCart(String p1);
iAdd$p1ToTheCart(product);
Fixed text and placeholders in the same value
Mix literal text into the quoted value and SpecBinder can no longer hand it over as one parameter, so it substitutes at the call site:
And I place the order with reference "ORD-<year>-<region>"
Then the tracking link should be "https://shop.example.com/orders/<region>/<year>"
public abstract void iPlaceTheOrderWithReference$p1(String p1);
iPlaceTheOrderWithReference$p1("ORD-<year>-<region>"
.replaceAll("<year>", year.toString())
.replaceAll("<region>", region));
Note year.toString(): year was inferred as Integer from its Examples column, while region
is already a String.
Inside a doc string
Same substitution, and the signature stays the plain trailing String a doc string always produces:
And I submit the order with the following payload:
"""json
{
"product": "<product>",
"quantity": "<qty>",
"total": "<total>"
}
"""
public abstract void iSubmitTheOrderWithTheFollowingPayload(String docString);
iSubmitTheOrderWithTheFollowingPayload("""
{
"product": "<product>",
"quantity": "<qty>",
"total": "<total>"
}
"""
.replaceAll("<product>", product)
.replaceAll("<qty>", qty.toString())
.replaceAll("<total>", total.toString()));
The json content type is for your IDE — highlighting and formatting. SpecBinder passes the content
through as a plain String either way.
Write "<qty>", not a bare <qty>. Substitution is textual, so the template itself must be
valid for its content type — and a bare <qty> is not valid JSON, so the IDE flags
"JSON standard does not allow such tokens".
The trade-off is real: "<qty>" substitutes to the JSON string "1", where a bare <qty> would
have produced the number 1.
Inside a data table
Every cell here is a placeholder, so the row is built straight from the scenario's parameters — with
types inferred from the Examples values:
Then the order should contain the following lines:
| product | quantity | line total |
| <product> | <qty> | <total> |
public abstract void theOrderShouldContainTheFollowingLines(List<LinesParam> lines);
theOrderShouldContainTheFollowingLines(List.of(new LinesParam(product, qty, total)));
LinesParam is generated with String product, Integer quantity and Double lineTotal.
Static cells and placeholders together
Placeholders don't have to fill the whole table. Static cells stay literal:
Then the order should show the following promotion details:
| field | value |
| promotion | <promo> |
| channel | web |
| discount | <discount> |
theOrderShouldShowTheFollowingPromotionDetails(List.of(
new DetailsParam("promotion", promo),
new DetailsParam("channel", "web"),
new DetailsParam("discount", discount)));
Run it
cd examples/common-use-cases/example-8
mvn test-compile
The generated class lands at
target/generated-test-sources/test-annotations/specs/ShoppingCartScenarios.java.