← All skills

Cucumber Skill

Bdd testingJavaJavaScriptRubyTypeScript

Copy and Paste in your Terminal

npx skills add https://github.com/LambdaTest/agent-skills.git --skill cucumber-skill

Advanced patterns

Advanced topics and patterns for experienced users.

Cucumber — Advanced Patterns & Playbook

Step Definitions with Transforms (Java)

public class StepDefinitions {
    private final WebDriver driver;
    private final World world;

    public StepDefinitions(World world) {
        this.world = world;
        this.driver = world.getDriver();
    }

    @Given("I am on the {page} page")
    public void navigateToPage(Page page) {
        driver.get(page.getUrl());
    }

    @When("I search for {string}")
    public void searchFor(String query) {
        world.searchPage.searchFor(query);
    }

    @Then("I should see {int} results")
    public void verifyResults(int count) {
        assertEquals(count, world.searchPage.getResultCount());
    }

    // Custom parameter type
    @ParameterType("home|login|dashboard|search")
    public Page page(String pageName) {
        return PageFactory.create(pageName);
    }
}

JavaScript Step Definitions

const { Given, When, Then, Before, After, setDefaultTimeout } = require('@cucumber/cucumber');
const { expect } = require('@playwright/test');

setDefaultTimeout(30_000);

Before(async function () {
  this.browser = await chromium.launch();
  this.page = await this.browser.newPage();
});

After(async function ({ result }) {
  if (result.status === 'FAILED') {
    const screenshot = await this.page.screenshot();
    this.attach(screenshot, 'image/png');
  }
  await this.browser?.close();
});

Given('I am logged in as {string}', async function (role) {
  await this.page.goto('/login');
  const creds = this.testData.getCredentials(role);
  await this.page.fill('#email', creds.email);
  await this.page.fill('#password', creds.password);
  await this.page.click('#submit');
  await expect(this.page).toHaveURL(/dashboard/);
});

When('I add {string} to cart', async function (product) {
  await this.page.click(`[data-product="${product}"] .add-to-cart`);
  await expect(this.page.locator('.cart-count')).toHaveText(/[1-9]/);
});

Then('the cart total should be {string}', async function (total) {
  const actual = await this.page.locator('.cart-total').textContent();
  expect(actual).toContain(total);
});

Scenario Outline with Examples

Feature: User Registration
  Background:
    Given the registration page is open

  Scenario Outline: Register with different data
    When I register with name "<name>" and email "<email>"
    Then I should see "<message>"

    Examples: Valid registrations
      | name    | email            | message     |
      | Alice   | alice@test.com   | Welcome     |
      | Bob     | bob@example.org  | Welcome     |

    Examples: Invalid registrations
      | name    | email   | message        |
      |         | a@b.com | Name required  |
      | Charlie | invalid | Invalid email  |

  @wip
  Scenario: Register with existing email
    Given a user with email "existing@test.com" exists
    When I register with name "Eve" and email "existing@test.com"
    Then I should see "Email already taken"

  Rule: Password requirements
    Scenario: Weak password rejected
      When I register with password "123"
      Then I should see "Password too weak"

Hooks & World Object

// Hooks.java
public class Hooks {
    @Before(order = 0)
    public void setupDriver(Scenario scenario) { /* ... */ }

    @Before("@database")
    public void seedDatabase() { testDb.seed(); }

    @After
    public void cleanup(Scenario scenario) {
        if (scenario.isFailed()) {
            byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
            scenario.attach(screenshot, "image/png", "failure");
        }
        driver.quit();
    }

    @BeforeStep
    public void logStep() { /* logging */ }
}

Anti-Patterns

  • ❌ Implementation details in feature files — keep Gherkin business-readable
  • ❌ One step per line that maps to a single WebDriver call — compose higher-level steps
  • And I wait 5 seconds — use implicit waits in step definitions
  • ❌ Scenario coupling via shared state — each scenario should be independent
  • ❌ Too many Given steps — use Background for shared setup