Skip to main content

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 stays String
  • 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?

BecomesSignature
"<product>" — whole valuea typed method parameterchanges
"ORD-<year>-<region>" — mixed with texta replaceAll at the call siteunchanged
doc string contenta replaceAll at the call siteunchanged
data table cella constructor argument at the call siteunchanged

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.

Quote your placeholders in a typed doc string

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.