Published Sep 16, 2025 ⦁ Updated Oct 11, 2026 ⦁ 9 min read
Scenario Outline in Cucumber: Examples and Step Definitions

Scenario Outline in Cucumber: Examples and Step Definitions

A Scenario Outline is a Gherkin template that runs the same steps once for each row of an Examples table. You write the steps with <placeholder> names that match the table's column headers, and Cucumber replaces them with each row's values before it looks for step definitions. Use it when several scenarios differ only in their data; use a plain Scenario when the steps themselves differ.

The syntax below follows the official Gherkin reference and works the same in Cucumber for JavaScript, Java and Ruby, in Reqnroll (the successor to SpecFlow for .NET), and in Behave for Python.

Scenario Outline syntax

Feature: Shipping cost

  Scenario Outline: Ship a <weight> kg parcel to <country>
    Given a parcel weighing <weight> kg
    When it is shipped to "<country>"
    Then the shipping cost is <cost> EUR

    Examples:
      | weight | country | cost  |
      | 1      | Germany | 4.99  |
      | 10     | Germany | 9.99  |
      | 1      | France  | 8.99  |

How it works:

  • Scenario Outline (synonym: Scenario Template) defines the template.
  • <weight>, <country>, <cost> are placeholders. Each must match a column header in the Examples table exactly.
  • Examples (synonym: Scenarios) holds the data. The first row is the header; every other row produces one scenario.
  • The outline above runs three scenarios. Cucumber also substitutes placeholders in the outline's title, so the report shows "Ship a 1 kg parcel to Germany", "Ship a 10 kg parcel to Germany", and so on.

Cucumber turns each row into an ordinary scenario before running it. The first row becomes:

Scenario: Ship a 1 kg parcel to Germany
  Given a parcel weighing 1 kg
  When it is shipped to "Germany"
  Then the shipping cost is 4.99 EUR

Scenario vs Scenario Outline

Scenario Scenario Outline
Runs Once Once per Examples row
Placeholders No Yes, <name>
Needs Examples No Yes, one or more
Best for One concrete example of a behavior The same behavior with several data sets
Report names Fixed Can include row values via placeholders in the title

If you find yourself copying a scenario and changing only the numbers, turn it into an outline. If the copies need different When or Then steps, keep them as separate scenarios.

How to write step definitions for a Scenario Outline

This is the part that confuses most people: step definitions never see <placeholder>. By the time Cucumber matches steps, the text is already Given a parcel weighing 1 kg. So you write normal step definitions with Cucumber Expressions parameters such as {int}, {float}, {string} and {word}.

JavaScript (cucumber-js)

// features/step_definitions/shipping.steps.js
const { Given, When, Then } = require('@cucumber/cucumber');
const assert = require('node:assert');
const { shippingCost } = require('../../src/shipping');

Given('a parcel weighing {int} kg', function (weight) {
  this.weight = weight;
});

When('it is shipped to {string}', function (country) {
  this.cost = shippingCost(this.weight, country);
});

Then('the shipping cost is {float} EUR', function (expected) {
  assert.strictEqual(this.cost, expected);
});

{string} matches text in double or single quotes and passes it without the quotes, which is why the feature file writes "<country>" in quotes.

Java (Cucumber-JVM)

import io.cucumber.java.en.*;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class ShippingSteps {
    private int weight;
    private double cost;

    @Given("a parcel weighing {int} kg")
    public void aParcelWeighing(int weight) {
        this.weight = weight;
    }

    @When("it is shipped to {string}")
    public void itIsShippedTo(String country) {
        cost = Shipping.cost(weight, country);
    }

    @Then("the shipping cost is {double} EUR")
    public void theShippingCostIs(double expected) {
        assertEquals(expected, cost, 0.001);
    }
}

The same three step definitions serve every row, and also any plain Scenario that uses the same wording.

Multiple Examples tables and tags

An outline can have several Examples sections. Give each one a name, and tag them separately to run subsets:

Scenario Outline: Ship a <weight> kg parcel to <country>
  Given a parcel weighing <weight> kg
  When it is shipped to "<country>"
  Then the shipping cost is <cost> EUR

  @domestic
  Examples: Domestic
    | weight | country | cost |
    | 1      | Germany | 4.99 |
    | 10     | Germany | 9.99 |

  @international @slow
  Examples: European Union
    | weight | country | cost  |
    | 1      | France  | 8.99  |
    | 10     | Spain   | 18.99 |

Per the Cucumber tags documentation, tags can go above Examples, and tags on the outline are inherited by all its Examples. Run a subset with a tag expression:

# cucumber-js
npx cucumber-js --tags "@domestic"
npx cucumber-js --tags "not @slow"

# Cucumber-JVM with Maven
mvn test -Dcucumber.filter.tags="@international and not @slow"

To run a single row while debugging, pass the file and the line number of that row: npx cucumber-js features/shipping.feature:12.

Scenario Outline with a data table or doc string

Placeholders also work inside step arguments. Cucumber replaces them in data table cells and doc strings, so you can combine an outline with a table:

Scenario Outline: Cart total with a discount code
  Given the cart contains:
    | item   | price   |
    | Book   | <book>  |
    | Pen    | <pen>   |
  When the customer applies the code "<code>"
  Then the total is <total>

  Examples:
    | book  | pen  | code    | total |
    | 20.00 | 2.00 | NONE    | 22.00 |
    | 20.00 | 2.00 | SAVE10  | 19.80 |

Use this sparingly. Two levels of tables in one scenario get hard to read quickly.

Scenario Outline vs Data Table: an Examples table runs the whole scenario once per row. A data table under a step passes all its rows to one step in one scenario run. Use Examples for "the same behavior with different inputs"; use a data table for "this one step needs a list of things".

Tips for writing good Scenario Outlines

  1. One behavior per outline. Every row should test the same rule. If rows need comments to explain why they differ, split the outline.
  2. Keep the table narrow. Three to five columns is readable. Beyond that, move setup details into a higher-level step like Given a premium customer.
  3. Choose rows that teach. Pick boundary values and the cases that explain the rule (zero, the limit, just over the limit) rather than ten similar rows. Exhaustive data belongs in unit tests.
  4. Name the outline with placeholders. A title like Ship a <weight> kg parcel to <country> makes failures in reports self-explanatory.
  5. Keep business language in the table. Write Germany or premium, not database IDs or JSON.
  6. Stay at 3-5 steps. The Gherkin reference recommends 3-5 steps per example; more steps make the specification harder to read.

For broader advice on structuring feature files, see 10 best practices for organizing BDD features and scenarios.

Common mistakes and how to debug them

  • "Undefined step" containing <something>. A placeholder didn't match a header (typo, different case, or extra spaces), so Cucumber left <something> in the step text. Make the header match exactly.
  • Step matches the wrong type. {int} won't match 4.99. Use {float} (or {double} in Java) for decimals.
  • Quotes missing. {string} needs the value in quotes in the feature file: "<country>", not <country>.
  • An Examples table with only a header. It produces zero scenarios, so the outline silently does nothing.
  • Logic hidden in the table. A column like expected_error_code with ten different values often means the outline is testing several rules at once.
  • Debugging a single failing row. Run it by line number (see above), or tag that Examples block @wip and run --tags "@wip".

Where Scenario Outlines fit in your toolchain

Scenario Outlines are part of Gherkin, so they work in any tool that parses .feature files: Cucumber, Reqnroll, Behave and pytest-bdd. Step definition syntax differs between them, but the feature file stays the same. New to Cucumber itself? Start with the Cucumber beginner guide, and browse testing tools on DevHunt for runners and reporting tools.

FAQ

What is a Scenario Outline in Cucumber?

It is a scenario template. Steps use <placeholders>, and Cucumber runs the scenario once for each row of the Examples table below it, substituting that row's values into the steps, the title, data tables and doc strings.

What is the difference between Scenario and Scenario Outline?

A Scenario runs once with fixed values. A Scenario Outline runs once per Examples row with values filled in from the table. Use an outline when several scenarios differ only in data.

Is Scenario Template different from Scenario Outline?

No. Scenario Template is a synonym of Scenario Outline, and Scenarios is a synonym of Examples. They behave identically; most teams use Scenario Outline and Examples because they are more common in documentation.

How do I write a step definition for a Scenario Outline?

Write it for the substituted text, not the placeholder. For Given a parcel weighing <weight> kg, the definition is Given('a parcel weighing {int} kg', ...). Cucumber matches each generated step against your definitions as if it were a normal scenario.

Can a Scenario Outline have more than one Examples table?

Yes. An outline needs at least one Examples section and can have several. Each can have its own name and tags, which lets you run, for example, only the @smoke rows in CI.