Configures Cucumber for BDD scenarios - Cucumber-JVM (Java/Kotlin via JUnit 5), Cucumber-JS (Node), Cucumber-Ruby. Authors `.feature` files in Gherkin, writes step definitions in the host language, runs via the framework's runner, integrates with JUnit XML reporting. Use when the user mentions Cucumber, Gherkin, `.feature` files, or behavior-driven (BDD) tests in Java, Kotlin, JavaScript, or Ruby, as the canonical wrapper for any of the three official implementations.
90
89%
Does it follow best practices?
Impact
91%
1.03xAverage score across 10 eval scenarios
Passed
No findings from the security scan
features/cart.feature and its step code have been stable for months. Last week
we turned on parallel execution to get the suite under five minutes, and since
then roughly one run in three fails - never the same scenario twice.
The failures come in two shapes. Sometimes it is TypeError: Cannot read properties of undefined (reading 'applyPromo'). Sometimes a total is wrong by
the exact amount of another scenario's cart, which is worse, because the numbers
look plausible enough that a reviewer waves them through.
Drop back to a single process and the file passes every time. Nobody has changed
src/cart.js.
The two scenarios that carry no starting cart of their own were written when the file always ran top to bottom, and they read whatever the previous scenario left behind.
Rework the step code (and the feature only as far as point 3 requires) so the suite is correct at any level of parallelism:
cucumber.js as it is - the point is to make
the suite correct under it, not to avoid it.src/cart.js is production code and must not change.Extract the following files before beginning.
=============== FILE: features/cart.feature =============== Feature: Shopping cart totals
Scenario: Two of the same item Given an empty cart And the cart contains 2 of "BOOK-001" at $12.50 Then the cart holds 2 items And the total is $25.00
Scenario: A promo applies to the whole cart Given an empty cart And the cart contains 1 of "BOOK-001" at $12.50 And the cart contains 3 of "MUG-014" at $7.00 When I apply the promo code "WELCOME10" Then the total is $30.15
Scenario: An unknown promo is rejected When I apply the promo code "NOTREAL" Then the promo is rejected And the total is $33.50
Scenario: Four of one item Given an empty cart And the cart contains 4 of "MUG-014" at $7.00 Then the cart holds 4 items And the total is $28.00
Scenario: The promo survives a repeated item When I apply the promo code "WELCOME10" Then the total is $25.20
=============== FILE: features/step_definitions/cart.steps.js =============== const assert = require('node:assert'); const { Given, When, Then } = require('@cucumber/cucumber'); const { Cart } = require('../../src/cart');
let cart; let promoAccepted;
Given('an empty cart', () => { cart = new Cart(); });
Given('the cart contains {int} of {string} at ${float}', (qty, sku, price) => { cart.add(sku, qty, price); });
When('I apply the promo code {string}', (code) => { promoAccepted = cart.applyPromo(code); });
Then('the cart holds {int} items', (expected) => { assert.strictEqual(cart.itemCount(), expected); });
Then('the total is ${float}', (expected) => { assert.strictEqual(cart.total(), expected); });
Then('the promo is rejected', () => { assert.strictEqual(promoAccepted, false); });
=============== FILE: src/cart.js =============== class Cart { constructor() { this.lines = []; this.discount = 0; }
add(sku, qty, price) { this.lines.push({ sku, qty, price }); }
itemCount() { return this.lines.reduce((n, line) => n + line.qty, 0); }
subtotal() { return this.lines.reduce((n, line) => n + line.qty * line.price, 0); }
applyPromo(code) { this.discount = code === 'WELCOME10' ? 0.1 : 0; return this.discount > 0; }
total() { return Number((this.subtotal() * (1 - this.discount)).toFixed(2)); } }
module.exports = { Cart };
=============== FILE: cucumber.js =============== module.exports = { default: { require: ['features/step_definitions//*.js', 'features/support//*.js'], format: ['progress'], parallel: 2, }, };
=============== FILE: package.json =============== { "name": "storefront-specs", "private": true, "scripts": { "bdd": "cucumber-js" }, "devDependencies": { "@cucumber/cucumber": "^10.9.0" } }