Cucumber reruns Background before every Examples row - when does that setup belong in a hook instead?
answer
- Every Examples row is a scenario
- Multiply steps by the row count
- A Background cannot be tagged
- Would deleting the line confuse the reader?
- Split the file or tag a hook
basics
~20 sBackground runs before every scenario, and each Examples row is its own scenario - so four Background steps above a 23-row outline run 92 times. Keep Background for context a reader needs; move machinery nobody reads into a tag-filtered hook.
solid answer
~50 sTwo things decide it. **Cost**: Background steps re-run for every scenario in the file, including every expanded `Examples` row, so their price is multiplied by a number the feature file does not show you. **Audience**: Background is part of the specification and is printed with every scenario, so a line that a domain reader does not need is noise in the document you asked them to trust. A Background also cannot be tagged - it applies to every scenario beneath it - so when most scenarios in the file do not need the setup you have exactly three moves: split the feature file, move the work into a hook selected by a tag, or make the setup cheap enough not to matter. Database resets, token minting and fixture seeding are machinery and belong in the hook; the business context the scenarios assume stays in `Background`.
code
gherkin · 16 linesFeature: Seed catalogue ordering
# only the facts the scenarios below actually depend on
Background:
Given the catalogue lists "Cherokee Trail of Tears" beans
# the warehouse fixture is machinery, established by a hook keyed on this tag
@needs-warehouse
Scenario Outline: Packets are reserved when an order is placed
When the buyer orders <packets> packets
Then <reserved> packets are reserved
Examples:
| packets | reserved |
| 3 | 3 |
| 17 | 17 |go deeper
Know that Background steps run again for every scenario in the file, and that setup nobody needs to read - resetting data, signing in - is better handled outside the feature file.
Explain the multiplication: each Examples row is its own scenario, so a four-step block above a 23-row table runs 92 times. Then give the placement test - would deleting the line make the scenarios harder to understand?
Show the operating judgement: measuring what a Background costs on a real suite, recognising that it cannot be tagged, and choosing between splitting the file, tagging a hook, or making the setup cheap. Bring numbers.
Own the convention across teams - what a Background is allowed to contain, who reviews additions to it, and how you keep specification and fixture machinery separated as suite ownership spreads across squads.
`Background` is Gherkin's shared-context block, and the design question is not what it does but what it should hold. Two properties of how Cucumber executes it decide almost every case. ## The multiplication nobody sees in the file Cucumber re-runs the Background steps before **each** scenario in the file, and a `Scenario Outline` is not one scenario - each `Examples` row expands into its own runnable scenario. So the cost is `Background steps x scenarios`, where the scenario count includes every row of every table. A seed-catalogue ordering service had a 4-step Background above one outline with 23 `Examples` rows: **92** Background step executions from a block that reads like four lines. At roughly 0.4 s per step that is 37 seconds added to a feature the file makes look trivial. Split over a 3-way parallel fork it is still a third of that on the critical path, and behind a merge queue that serialises everything it lands on every merge, not once a day. The file gives you no hint of this. That is why Background cost is a senior-level reading skill: you have to multiply by the row count in your head. ## Specification or machinery The second test is about the reader, not the clock. Background text is printed with every scenario in reports, so it is part of the document. Ask: **if I deleted this line, would the scenarios below become harder to understand?** | Line | Verdict | Where it goes | |---|---|---| | the catalogue lists 'Cherokee Trail of Tears' beans | Context a reader needs | `Background` | | "the database is reset" | Machinery | Hook | | "an authentication token has been minted" | Machinery | Hook | | "the buyer has a confirmed account" | Context, if the rules depend on it | `Background` | | "the screenshot directory is cleaned" | Machinery | Hook | Machinery in `Background` has a second cost beyond time: it teaches readers that the feature file is a script, and every subsequent scenario is written in that register. ## The three levers when most scenarios do not need it `Background` cannot be tagged and cannot be applied to a subset - it covers every scenario beneath it. So when only some scenarios need the setup: 1. **Split the feature file.** If two groups of scenarios need genuinely different context, they are two features. This is the move people skip because the file has a tidy name, and it is usually the right one. 2. **Move the work into a hook selected by a tag.** Every implementation offers this: Cucumber-JVM's `@Before` takes a tag expression, cucumber-js accepts tags when registering a `Before` hook, Behave inspects the scenario's tags in `environment.py`, SpecFlow/Reqnroll filters a `[BeforeScenario]` binding by tag. The scenarios that need the fixture carry the tag; the rest pay nothing and their reports stay clean. 3. **Make it cheap instead of moving it.** Sometimes the setup genuinely is context every scenario needs. Then the answer is not relocation but cost: seed through a service call rather than the interface, reuse a prepared fixture, keep the Background to the two or three facts that matter. ## What stays Keep `Background` short - a handful of Given lines, no `When`, no `Then`. Keep it to facts the scenarios below actually depend on. Resist the "shared setup" reflex that grows it one line at a time until it is the longest block in the file and half the scenarios are unaffected by two thirds of it. A practical review habit: for each Background line, count how many scenarios in the file would fail if it were removed. A line that only two of eleven scenarios need is in the wrong place, whatever the file's name suggests. ## Ordering, briefly Hook code registered to run before a scenario executes before the Background steps do, which is what makes the split workable: the hook establishes the machinery, the Background states the facts, and the scenario reads as specification with no fixture noise in it. The precise hook levels and their ordering rules are a topic of their own; for scenario design, what matters is that the hook path exists and is selectable by tag while `Background` is neither. ## The failure mode this prevents The suite where every feature opens with eleven Background lines, most scenarios need three of them, and the run takes minutes longer than the work it does. Nobody deletes a Background line because nobody can tell which scenarios depend on it - so it grows forever. Deciding placement at write time, on the two tests above, is what stops that accumulation.
- The Background really is needed by every scenario but it is slow. What do you do?Do not relocate it - it is specification and the reader needs it. Attack the cost instead: reach the state through a service call rather than the interface, reuse a prepared fixture instead of rebuilding it, and trim the block to the facts scenarios actually depend on. Relocating context into a hook only hides a cost you still pay.
- How do you choose between splitting the feature file and tagging a hook?Split when the two groups of scenarios describe different behaviour and merely shared a filename - the file was doing two jobs. Tag a hook when the scenarios belong together but only some need a fixture, which is a machinery difference rather than a subject difference. If splitting would leave each file with one scenario, tag instead.
- How do you decide whether an existing Background line has earned its place?Count how many scenarios in the file would fail without it, and ask whether a domain reader needs it to follow the ones below. A line most scenarios do not need is misplaced; a line every scenario needs but nobody reads is machinery. Only lines passing both tests belong in the block.
Background is the opening paragraph of a document; a hook is the stage crew setting up before the curtain. Anything the audience does not need to hear belongs to the crew.
saying these in an interview costs you the question
- Forgets each Examples row re-runs the Background
- Thinks Background executes once per feature file
- Puts database resets and logins in Background
- Believes a Background can be limited by a tag
- Grows Background whenever two scenarios share a step
- Moves genuine business context out of the specification