Using Cucumber Background Blocks to Reduce Duplicated Given Steps
Learn how Cucumber Background blocks eliminate duplicated Given steps, see a concrete example, and understand the shared‑state trade‑off.
31 Dec 2025, 14:11 UTC

Problem: Repeated Given Steps Make Feature Files Hard to Maintain
When writing BDD scenarios with Cucumber, it is common to start each scenario with the same set of Given steps—for example, creating a test user, clearing a cache, or seeding a database. Repeating these steps clutters the feature file, makes updates error‑prone, and obscures the actual behavior being tested.
Thesis: A Background block lets you declare shared preconditions once, and Cucumber will run them before every scenario in the same feature file.
How Background Works
A Background section lives at the top of a feature file, before the first Scenario. Cucumber treats every step inside it as an implicit Given and executes it before each scenario, regardless of tags. If a step definition is missing, Cucumber reports an "undefined step" error and halts execution, just like with any other step.
Because the Background runs in the same test execution context as the scenarios, any side‑effects (e.g., database rows, files) persist unless you explicitly clean them up.
Worked Example: Setting Up a Test User
Suppose we have a feature for managing user profiles. Instead of repeating the user‑creation steps, we place them in a Background.
# user_profile.feature
Feature: User profile management
Background:
Given the test database is empty
And I create a test user with username "alice" and password "secret"
And I log in as "alice"
Scenario: View own profile
When I navigate to "/profile"
Then I should see "Welcome, alice"
Scenario: Update email
When I change my email to "[contact removed]"
Then I should receive a confirmation email
Step definitions (Java/JVM example) might look like:
@Given("the test database is empty")
public void clearDatabase() {
// truncate tables or reset state
}
@Given("I create a test user with username {string} and password {string}")
public void createUser(String username, String password) {
// call user service to create account
}
@Given("I log in as {string}")
public void login(String username) {
// perform login via UI or API
}
To verify that the Background runs before each scenario, execute a dry‑run:
cucumber --dry-run src/test/resources/features/user_profile.feature
The console output will list the Background steps followed by each scenario’s steps, confirming that the shared preconditions are executed twice (once per scenario).
Trade‑off: Shared State Can Cause Flaky Tests
Because the Background shares the same context, any mutable state left behind by a scenario will be visible to the next scenario. For example, if a scenario creates a temporary file and does not delete it, a later scenario might incorrectly find that file and pass or fail unexpectedly.
Limitation: You must explicitly reset or clean up resources either in an After hook or at the end of the Background if the state is not scenario‑specific.
Actionable Checklist
- Identify repetitive
Givenblocks across scenarios. - Move those steps into a
Backgroundsection at the top of the feature. - Ensure every Background step has a matching step definition on the test runner’s classpath.
- Add a unique marker step (e.g.,
Given I set a marker token 'VERIFY_BACKGROUND') that logs a value; run the feature and confirm the marker appears before each scenario. - Review each Background step for side‑effects and add cleanup in an
Afterhook or at the end of the Background. - Use tag expressions (
--tags ~@wip) in CI to run only the scenarios you need while still benefiting from the shared Background.
By centralizing preconditions with a Background, you keep feature files readable, reduce duplication, and maintain a single source of truth for test setup—provided you manage shared state carefully.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.