BDD / Cucumber
12 challenges covering Gherkin syntax, Scenario Outline, hooks, tags, World objects, step definitions, and when to use BDD.
Challenge 1BeginnerGherkin
Solved
What do Given, When, and Then represent?
In a Gherkin scenario, each keyword has a specific semantic role. Match each keyword to its role.
Scenario: User logs in successfully
Given the user is on the login page
When the user enters valid credentials
Then the dashboard should be displayedAnswer: B — Given=context, When=action, Then=outcome
The three-part Gherkin structure maps directly to test structure: Given sets up the initial state (precondition) — the system is in a known state. When describes the actor's action that triggers the behavior being tested. Then describes the expected observable outcome that should result. This structure forces testers to think clearly about state, trigger, and expected result — making scenarios precise and readable by non-technical stakeholders.
The three-part Gherkin structure maps directly to test structure: Given sets up the initial state (precondition) — the system is in a known state. When describes the actor's action that triggers the behavior being tested. Then describes the expected observable outcome that should result. This structure forces testers to think clearly about state, trigger, and expected result — making scenarios precise and readable by non-technical stakeholders.
Challenge 2IntermediateGherkin
Solved
What is the purpose of Scenario Outline with Examples?
You want to run the same login scenario with 5 different username/password combinations. What Gherkin feature handles this?
Scenario Outline: Login with different roles
Given I am on the login page
When I login as "<username>" with "<password>"
Then I should see "<expectedPage>"
Examples:
| username | password | expectedPage |
| admin | admin123 | /dashboard |
| viewer | view456 | /reports |Answer: B — one execution per Examples row
Scenario Outline is Gherkin's parameterization mechanism. Each row in the
Scenario Outline is Gherkin's parameterization mechanism. Each row in the
Examples table produces a completely independent scenario run. With 2 rows, you get 2 test executions. The <placeholder> syntax in the scenario steps is replaced with actual values from each row at runtime. This avoids duplicating near-identical scenarios — you write the structure once and vary only the data.Challenge 3BeginnerGherkin
Solved
What does the Background keyword do?
You have a feature file where every scenario starts with the same 2 steps:
Given I am logged in and Given I am on the home page. How do you avoid repeating them?Answer: B — Background runs before every scenario in the file
Background: is a section at the top of a feature file, after the feature description and before any scenarios. Steps listed under Background: run automatically before EVERY scenario in that feature file. It's like a beforeEach but written in Gherkin. Keep Background steps short — only include truly universal preconditions. If only some scenarios share setup, use separate Given steps instead.Challenge 4IntermediateHooks
Solved
What does a @Before hook do in Cucumber?
When does a
@Before hook run in Cucumber-Playwright, and how does it differ from Gherkin's Background:?Answer: B — @Before is a code hook; Background is Gherkin
@Before hooks are written in TypeScript/JavaScript and run before each scenario's steps execute. They are used for technical setup: launching browsers, setting up page state, seeding test data. Background: runs Gherkin steps visible in test reports, good for business-readable preconditions. Key difference: @Before can be tagged: @Before({ tags: '@smoke' }) — runs only for @smoke scenarios. Background always runs for all scenarios in its feature file.Challenge 5BeginnerTags
Solved
How do you run only @smoke scenarios?
Your feature files have scenarios tagged with
@smoke and @regression. You want to run only @smoke scenarios. What CLI command works?Answer: B — --tags "@smoke"
The
The
--tags flag filters scenarios by their Gherkin tags. Tag expressions support logic: --tags "@smoke and not @slow" runs smoke but excludes slow scenarios. --tags "@smoke or @sanity" runs either. Tags can be placed on individual scenarios, on Scenario Outlines (applies to all examples), or on an entire Feature (tags all scenarios in the file). Use tags to organize tests by priority, environment, or feature area.Challenge 6IntermediateWorld
Solved
What is the World object in Cucumber?
Multiple step definitions in the same scenario need to share data (like a logged-in user's name). How does Cucumber enable this without global variables?
Answer: B — per-scenario shared context (this)
The World is an object instance that Cucumber creates fresh for each scenario. All step definitions bound to that scenario share the same World via
The World is an object instance that Cucumber creates fresh for each scenario. All step definitions bound to that scenario share the same World via
this: Given('I logged in as {string}', function(username) { this.loggedInUser = username; }); Then('I should see my name', function() { expect(this.page).toContain(this.loggedInUser); }). Custom World classes can hold page objects: class CustomWorld { page!: Page; }. Each scenario gets a new World — no state leaks between scenarios.Challenge 7IntermediateStep Defs
Solved
How do step definitions extract parameters from step text?
Your Gherkin step is
When I login as "admin" with password "secret". How does the step definition capture "admin" and "secret"?When('I login as {string} with password {string}',
async function(username: string, password: string) {
await this.page.getByLabel('Username').fill(username);
await this.page.getByLabel('Password').fill(password);
}
);Answer: B — Cucumber Expressions like {string}, {int}
Cucumber Expressions are the modern way to capture parameters.
Cucumber Expressions are the modern way to capture parameters.
{string} matches a quoted string (removes quotes). {int} matches an integer. {float} matches a decimal. {word} matches a single word. They are passed as typed arguments to the function. You can also use regex: When(/I login as "(.*)" with "(.*)"/, async function(u, p) {...}) — the capture groups become arguments. Cucumber Expressions are cleaner and more readable than regex.Challenge 8AdvancedData Tables
Solved
How do you use a Data Table in a step definition?
Your step has an inline table. How does the step definition access the table data?
When I fill the registration form:
| field | value |
| firstName | Alice |
| email | alice@test.com |Answer: B — DataTable last argument, use table.hashes()
When a step has an attached table, Cucumber passes a
When a step has an attached table, Cucumber passes a
DataTable object as the last parameter. Key methods: table.hashes() — returns [{field:'firstName',value:'Alice'},{field:'email',value:'alice@test.com'}] (header row becomes keys). table.rows() — returns all rows as string arrays, EXCLUDING the header. table.raw() — all rows INCLUDING header. For key-value style tables, table.rowsHash() converts to a single object: {firstName: 'Alice', email: 'alice@test.com'}.Challenge 9BeginnerStructure
Solved
Where should feature files be located in a project?
Your team is setting up a new Cucumber-Playwright project. What is the recommended convention for organizing feature files?
Answer: B — separate features/ directory by business domain
Convention: keep feature files in a top-level
Convention: keep feature files in a top-level
features/ directory (or tests/features/) organized by business domain: features/authentication/, features/checkout/, features/reporting/. Step definitions go in features/step-definitions/ or steps/. One feature file per user story or functional area — not one gigantic file. Feature files are written by product/QA and should be readable without technical knowledge, which is why they stay separate from implementation code.Challenge 10AdvancedTrade-offs
Solved
What is the main overhead of Cucumber vs native Playwright tests?
A team is deciding whether to use Cucumber-Playwright vs plain Playwright tests. What is the primary trade-off?
Answer: B — the translation layer only pays off with active stakeholder collaboration
Cucumber's value proposition is living documentation — feature files written in Gherkin are readable by product owners, business analysts, and QA. But this requires: (1) stakeholders actually reading/writing feature files; (2) maintaining the Gherkin-to-code mapping; (3) learning Cucumber-specific concepts (World, hooks, step binding). If only developers write and read tests, plain Playwright is simpler and more powerful. Cucumber adds real value when BDD collaboration is genuinely practiced.
Cucumber's value proposition is living documentation — feature files written in Gherkin are readable by product owners, business analysts, and QA. But this requires: (1) stakeholders actually reading/writing feature files; (2) maintaining the Gherkin-to-code mapping; (3) learning Cucumber-specific concepts (World, hooks, step binding). If only developers write and read tests, plain Playwright is simpler and more powerful. Cucumber adds real value when BDD collaboration is genuinely practiced.
Challenge 11BeginnerStep Defs
Solved
How are step definitions reused across different scenarios?
The step
Given I am logged in as "admin" appears in 20 scenarios across 5 feature files. Do you need to define the step implementation 20 times?Answer: B — one definition matches globally
Cucumber loads all step definition files at startup and creates a global registry of pattern → function mappings. When any scenario across any feature file contains
Cucumber loads all step definition files at startup and creates a global registry of pattern → function mappings. When any scenario across any feature file contains
Given I am logged in as "admin", Cucumber finds the matching step definition and executes it. This is the core reuse mechanism — write the step implementation once, use it everywhere. Duplicate step definitions (same pattern defined twice) cause an ambiguity error at runtime.Challenge 12BeginnerGherkin
Solved
What are And and But keywords in Gherkin?
You have multiple consecutive Given or When steps. What is the purpose of
And and But?Given I am on the checkout page
And my cart has 3 items
And I have entered my address
When I click "Place Order"
Then I should see the confirmation page
But I should not see any error messageAnswer: B — syntactic sugar for the preceding keyword
And and But are purely for readability — they have no semantic difference from the previous keyword. In the example: the And steps after Given are treated as Given steps. But after Then is treated as Then. This allows natural English flow: "Given... And... And..." reads better than "Given... Given... Given...". Step definitions are registered with Given(), When(), or Then() — not And() or But() — because they inherit the previous step's type.