Skip to content
cucumber-best-practices logo

Cucumber Best Practices

cucumber-best-practices

Cucumber best practices, patterns, and anti-patterns

TheBushidoCollective/han0installs199stars

SKILL.md

Full skill instructions

Cucumber Best Practices

Master patterns and practices for effective Cucumber testing.

Scenario Design Principles

1. Write Declarative Scenarios

Focus on what needs to happen, not how it happens.

❌ Imperative (implementation-focused):

Scenario: Add product to cart
  Given I navigate to "http://shop.com/​products"
  When I find the element with CSS ".product[data-id='123']"
  And I click the button with class "add-to-cart"
  And I wait for the AJAX request to complete
  Then the element ".cart-count" should contain "1"

✅ Declarative (business-focused):

Scenario: Add product to cart
  Given I am browsing products
  When I add "Wireless Headphones" to my cart
  Then my cart should contain 1 item

2. One Scenario, One Behavior

Each scenario should test exactly one business rule or behavior.

❌ Multiple behaviors in one scenario:

Scenario: User registration and login and profile update
  Given I register a new account
  When I log in
  And I update my profile
  And I change my password
  Then everything should work

✅ Separate scenarios:

Scenario: Register new account
  When I register with valid details
  Then I should receive a confirmation email

Scenario: Login with new account
  Given I have registered an account
  When I log in with my credentials
  Then I should see my dashboard

Scenario: Update profile
  Given I am logged in
  When I update my profile information
  Then my changes should be saved

3. Keep Scenarios Independent

Each scenario should set up its own preconditions.

❌ Dependent scenarios:

Scenario: Create order
  When I create order #12345

Scenario: View order
  When I view order #12345  # Depends on previous scenario!

✅ Independent scenarios:

Scenario: View order
  Given an order exists with ID "12345"
  When I view the order details
  Then I should see the order information

4. Use Background Wisely

Use Background for common setup, but don't overuse it.

✅ Good use of Background:

Feature: Shopping Cart

  Background:
    Given I am logged in as a customer

  Scenario: Add product to cart
    When I add a product to my cart
    Then my cart should contain 1 item

  Scenario: Remove product from cart
    Given I have a product in my cart
    When I remove the product
    Then my cart should be empty

❌ Background doing too much:

Background:
  Given I am on the homepage
  And I click the menu
  And I navigate to products
  And I filter by category "Electronics"
  And I sort by price
  # Too much setup! Not all scenarios need all of this

Feature Organization

Group Related Scenarios

Feature: User Authentication

  Scenario: Successful login
    ...

  Scenario: Failed login with wrong password
    ...

  Scenario: Account lockout after multiple failures
    ...

Use Tags Effectively

@smoke @critical
Scenario: Login with valid credentials
  ...

@slow @integration
Scenario: Password reset email workflow
  ...

@wip
Scenario: OAuth login
  # Work in progress
  ...

Run specific tags:

# Run smoke tests
cucumber --tags "@smoke"

# Run all except WIP
cucumber --tags "not @wip"

# Run smoke AND critical
cucumber --tags "@smoke and @critical"

# Run smoke OR critical
cucumber --tags "@smoke or @critical"

Writing Good Gherkin

Use Domain Language

Write in the language of the business domain, not technical terms.

❌ Technical language:

Scenario: POST request to /​api/​users
  When I send a POST to "/​api/​users" with JSON payload
  And the response status is 201

✅ Domain language:

Scenario: Register new user
  When I register a new user account
  Then the user should be created successfully

Keep Steps at the Same Level

Don't mix high-level and low-level details.

❌ Mixed levels:

Scenario: Purchase product
  Given I am logged in
  When I add a product to cart
  And I click the element with ID "checkout-btn"  # Too detailed!
  And I enter credit card "4111111111111111"      # Too detailed!
  Then I complete the purchase

✅ Consistent level:

Scenario: Purchase product
  Given I am logged in
  And I have a product in my cart
  When I checkout with a credit card
  Then my order should be completed
  And I should receive a confirmation email

Avoid Conjunctive Steps

Don't use "And" to combine multiple distinct actions in prose.

❌ Conjunctive step:

When I log in and add a product to cart and checkout

✅ Separate steps:

When I log in
And I add a product to my cart
And I proceed to checkout

Scenario Outlines

Use for True Variations

Use Scenario Outlines when you need to test the same behavior with different data.

✅ Good use:

Scenario Outline: Login validation
  When I log in with "<username>" and "<password>"
  Then I should see "<message>"

  Examples:
    | username | password | message                |
    | valid    | valid    | Welcome                |
    | invalid  | valid    | Invalid username       |
    | valid    | invalid  | Invalid password       |
    | empty    | empty    | Username required      |

❌ Overusing Scenario Outline:

# Don't use Scenario Outline for unrelated test cases
Scenario Outline: Multiple features
  When I use feature "<feature>"
  Then result is "<result>"

  Examples:
    | feature        | result    |
    | login          | success   |
    | registration   | success   |
    | cart           | empty     |  # These are different behaviors!

Keep Examples Meaningful

Scenario Outline: Discount calculation
  Given a customer with "<membership>" status
  When they purchase items totaling $<amount>
  Then they should receive a $<discount> discount

  Examples: Standard discounts
    | membership | amount | discount |
    | silver     | 100    | 5        |
    | gold       | 100    | 10       |
    | platinum   | 100    | 15       |

  Examples: Minimum purchase thresholds
    | membership | amount | discount |
    | silver     | 49     | 0        |
    | silver     | 50     | 2.50     |

Step Definition Patterns

Create Reusable Steps

// Generic, reusable
When('I fill in {string} with {string}', async function(field, value) {
  await this.page.fill(`[name="${field}"]`, value);
});

// Used in multiple scenarios:
When('I fill in "email" with "[email protected]"')
When('I fill in "password" with "secure123"')
When('I fill in "search" with "products"')

Avoid Over-Generic Steps

Balance reusability with readability.

❌ Too generic:

When('I do {string} with {string} and {string}', ...)

✅ Specific and readable:

When('I log in with {string} and {string}', ...)
When('I search for {string} in {string}', ...)

Data Management

Use Factories for Test Data

// support/​factories.js
const faker = require('faker');

class UserFactory {
  static create(overrides = {}) {
    return {
      firstName: faker.name.firstName(),
      lastName: faker.name.lastName(),
      email: faker.internet.email(),
      password: 'Test123!',
      ...overrides
    };
  }
}

// Use in steps
Given('I register a new user', async function() {
  const user = UserFactory.create();
  this.currentUser = user;
  await this.api.register(user);
});

Avoid Hardcoded IDs

❌ Hardcoded:

Given user "12345" exists
When I view order "67890"

✅ Named entities:

Given a user "[email protected]" exists
When I view my most recent order

Error Handling

Test Happy and Unhappy Paths

@happy-path
Scenario: Successful checkout
  Given I have items in my cart
  When I complete the checkout process
  Then my order should be confirmed

@error-handling
Scenario: Checkout with expired card
  Given I have items in my cart
  When I checkout with an expired credit card
  Then I should see an error message
  And my order should not be processed

@edge-case
Scenario: Checkout with insufficient inventory
  Given I have a product in my cart
  But the product is out of stock
  When I attempt to checkout
  Then I should be notified about stock unavailability

Performance

Tag Slow Tests

@slow @integration
Scenario: Full order workflow with email notifications
  # Takes 30 seconds to run
  ...

Parallel Execution

Ensure scenarios can run in parallel:

// cucumber.js
module.exports = {
  default: '--parallel 4'
};

Maintenance

Regular Review

  • Remove obsolete scenarios
  • Update scenarios when requirements change
  • Refactor duplicate steps
  • Keep features organized

Version Control

features/
  authentication/
    login.feature
    registration.feature
  shopping/
    cart.feature
    checkout.feature
  admin/
    user-management.feature

Common Anti-Patterns

❌ Testing implementation details:

Then the database should have 1 record in the users table

❌ UI-specific assertions in business scenarios:

Then I should see a red error message in the top right corner

❌ Using Given for actions:

Given I click the submit button  # This is a When, not a Given!

❌ Technical jargon:

When I POST to /​api/​v1/​users with JSON body

Testing Pyramid

Use Cucumber appropriately in your test strategy:

  • E2E Cucumber Tests: Critical user journeys (20%)
  • Integration Tests: API/​service interactions (30%)
  • Unit Tests: Business logic (50%)

Don't try to test everything with Cucumber. Use it for high-value acceptance tests.

Remember: Cucumber tests should document behavior, facilitate collaboration, and provide confidence that the system works as expected from a business perspective.

More skills from TheBushidoCollective

typescript-utility-types logo
TheBushidoCollective/han

typescript-utility-types

Use when typeScript utility types, mapped types, and advanced type manipulation. Use when creating flexible, type-safe TypeScript code.

199 0
View
shell-portability logo
TheBushidoCollective/han

shell-portability

Use when writing shell scripts that need to run across different systems, shells, or environments. Covers POSIX compatibility and platform differences.

199 0
View
tailwind-performance logo
TheBushidoCollective/han

tailwind-performance

Use when optimizing Tailwind CSS for production, reducing bundle size, and improving performance. Covers PurgeCSS, JIT mode, and build optimization.

199 0
View
figma-generate-component logo
TheBushidoCollective/han

figma-generate-component

Generate production-ready code from a Figma component or frame using the Figma MCP server

199 0
View
dialyzer-integration logo
TheBushidoCollective/han

dialyzer-integration

Use when integrating Dialyzer into development workflows and CI/CD pipelines for Erlang/Elixir projects.

199 0
View
rubocop-configuration logo
TheBushidoCollective/han

rubocop-configuration

Use when ruboCop configuration including YAML config, departments, inheritance, and customization.

199 0
View
elixir-otp-patterns logo
TheBushidoCollective/han

elixir-otp-patterns

Use when Elixir OTP patterns including GenServer, Supervisor, Agent, and Task. Use when building concurrent, fault-tolerant Elixir applications.

199 0
View
ameba-custom-rules logo
TheBushidoCollective/han

ameba-custom-rules

Use when creating custom Ameba rules for Crystal code analysis including rule development, AST traversal, issue reporting, and rule testing.

199 0
View
Swift Optionals Patterns logo
TheBushidoCollective/han

Swift Optionals Patterns

Use when swift's optional handling patterns including optional binding, chaining, nil coalescing, and modern approaches to safely working with optional values while avoiding common pitfalls and force unwrapping.

199 0
View
code-annotation-patterns logo
TheBushidoCollective/han

code-annotation-patterns

Use when annotating code with structured metadata, tags, and markers for AI-assisted development workflows. Covers annotation formats, semantic tags, and integration with development tools.

199 0
View
Scala Collections logo
TheBushidoCollective/han

Scala Collections

Use when scala collections including immutable/mutable variants, List, Vector, Set, Map operations, collection transformations, lazy evaluation with views, parallel collections, and custom collection builders for efficient data processing.

199 0
View
reactflow-custom-nodes logo
TheBushidoCollective/han

reactflow-custom-nodes

Use when creating custom React Flow nodes, edges, and handles. Covers custom node components, resizable nodes, toolbars, and advanced customization.

199 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View