TestKase Docs
AutomationTest Frameworks

Cucumber

Set up Cucumber for BDD testing and integrate test results with TestKase.

Overview

Cucumber is a BDD (Behavior-Driven Development) framework that lets you write tests in Gherkin syntax using natural language constructs — Given, When, Then. It bridges the gap between business stakeholders and developers by making test scenarios readable by everyone. Cucumber supports JavaScript, Java, Ruby, and other languages.

To integrate Cucumber results with TestKase, generate JSON output and report with --format cucumber.

Prerequisites

  • Node.js 18+ (for JavaScript) or Java 11+ (for Java)
  • A project to test

Installation

JavaScript

Install Cucumber as a dev dependency:

npm install --save-dev @cucumber/cucumber

Java (Maven)

Add Cucumber dependencies to your pom.xml:

<dependencies>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>7.15.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit-platform-engine</artifactId>
        <version>7.15.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-suite</artifactId>
        <version>1.10.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Project Setup

JavaScript

Create a cucumber.js configuration file in your project root:

// cucumber.js
module.exports = {
  default: {
    paths: ['features/**/*.feature'],
    require: ['features/step_definitions/**/*.js'],
    format: [
      'progress-bar',
      'json:test-results/cucumber.json',
    ],
    publishQuiet: true,
  },
};

JavaScript Directory Structure

my-project/
  cucumber.js
  package.json
  features/
    login.feature
    dashboard.feature
    step_definitions/
      login_steps.js
      dashboard_steps.js
    support/
      world.js
  test-results/           # Generated after running tests
    cucumber.json

Java

Create a runner class and configure the feature/step paths. Place feature files under src/test/resources/features/ and step definitions under src/test/java/:

my-project/
  pom.xml
  src/
    test/
      java/com/example/
        steps/
          LoginSteps.java
        RunCucumberTest.java
      resources/
        features/
          login.feature
        cucumber.properties

Create the cucumber.properties file:

# src/test/resources/cucumber.properties
cucumber.plugin=pretty, json:test-results/cucumber.json
cucumber.glue=com.example.steps

Writing Tests

Feature File

Create a .feature file with Gherkin syntax (e.g., features/login.feature):

# features/login.feature
Feature: Login

  Users should be able to log in with valid credentials
  and see appropriate error messages for invalid attempts.

  Scenario: [48271] User logs in with valid credentials
    Given the user is on the login page
    When the user enters "user@example.com" and "password123"
    And the user clicks the login button
    Then the user should be redirected to the dashboard

  Scenario: [48272] User sees error for invalid password
    Given the user is on the login page
    When the user enters "user@example.com" and "wrong"
    And the user clicks the login button
    Then the user should see the error "Invalid credentials"

  Scenario Outline: [48273] User logs in with multiple accounts
    Given the user is on the login page
    When the user enters "<email>" and "<password>"
    And the user clicks the login button
    Then the login result should be "<result>"

    Examples:
      | email              | password    | result  |
      | user@example.com   | password123 | success |
      | admin@example.com  | admin456    | success |
      | bad@example.com    | wrong       | failure |

Step Definitions (JavaScript)

Create step definitions that match the Gherkin steps (e.g., features/step_definitions/login_steps.js):

// features/step_definitions/login_steps.js
const { Given, When, Then } = require('@cucumber/cucumber');
const assert = require('assert');

Given('the user is on the login page', async function () {
  await this.page.goto('/login');
});

When('the user enters {string} and {string}', async function (email, password) {
  await this.page.fill('[data-testid="email"]', email);
  await this.page.fill('[data-testid="password"]', password);
});

When('the user clicks the login button', async function () {
  await this.page.click('[data-testid="login-button"]');
});

Then('the user should be redirected to the dashboard', async function () {
  assert.ok(this.page.url().includes('/dashboard'));
});

Then('the user should see the error {string}', async function (message) {
  const error = await this.page.textContent('.error-message');
  assert.strictEqual(error, message);
});

Then('the login result should be {string}', async function (result) {
  if (result === 'success') {
    assert.ok(this.page.url().includes('/dashboard'));
  } else {
    const error = await this.page.locator('.error-message');
    assert.ok(await error.isVisible());
  }
});

Each Scenario name includes a 5-digit Automation ID in square brackets. The @testkase/reporter CLI extracts these IDs using the regex \[(\d{5})\]. For the example above:

  • 48271 → linked to the "valid login" test case in TestKase
  • 48272 → linked to the "invalid password" test case in TestKase
  • 48273 → linked to the "multiple accounts" test case in TestKase

Generate Automation IDs in TestKase first, then embed them in your Scenario names. The [XXXXX] pattern can appear anywhere in the Scenario name — the reporter extracts all 5-digit IDs found in brackets.

Running Tests

JavaScript

Run Cucumber with JSON output:

npx cucumber-js

If the format option is configured in cucumber.js, the JSON file is generated automatically. To override on the command line:

npx cucumber-js --format json:test-results/cucumber.json

Java

Run with Maven:

mvn test

The JSON plugin configured in cucumber.properties generates the output file automatically.

TestKase Integration

After generating the Cucumber JSON file, report results to TestKase:

npx @testkase/reporter report \
  --token $TESTKASE_PAT \
  --project-id PRJ-1 \
  --org-id 1173 \
  --cycle-id TCYCLE-5 \
  --format cucumber \
  --results-file test-results/cucumber.json

--cycle-id is optional. If not provided, results are reported to TCYCLE-1 — the master test cycle for the project.

Automation ID Mapping

The reporter extracts 5-digit Automation IDs from Cucumber Scenario names using the [XXXXX] bracket pattern:

Test PatternScenario NameExtracted ID
Standard Scenario[48271] User logs in with valid credentials48271
Another Scenario[48272] User sees error for invalid password48272
Scenario Outline[48273] User logs in with multiple accounts48273

For Scenario Outline tests, all Example rows share the same [XXXXX] Automation ID. The TestKase reporter aggregates results from all Example rows into a single test result.

The [XXXXX] pattern can appear anywhere in the Scenario name. Generate the 5-digit ID in TestKase first, then embed it in your feature file.

Complete Example

1. Feature File

# features/login.feature
Feature: Login

  Scenario: [48271] User logs in with valid credentials
    Given the user is on the login page
    When the user enters "user@example.com" and "password123"
    And the user clicks the login button
    Then the user should be redirected to the dashboard

  Scenario: [48272] User sees error for invalid password
    Given the user is on the login page
    When the user enters "user@example.com" and "wrong"
    And the user clicks the login button
    Then the user should see the error "Invalid credentials"

2. Run Tests and Generate JSON

npx cucumber-js --format json:test-results/cucumber.json

3. Report Results to TestKase

npx @testkase/reporter report \
  --token $TESTKASE_PAT \
  --project-id PRJ-1 \
  --org-id 1173 \
  --cycle-id TCYCLE-5 \
  --format cucumber \
  --results-file test-results/cucumber.json

Troubleshooting

JSON output file is empty

If the cucumber.json file is empty or contains [], verify the format option syntax in your configuration:

// cucumber.js — correct format syntax
module.exports = {
  default: {
    format: ['json:test-results/cucumber.json'],
  },
};

Common mistakes:

  • Missing the colon between format name and file path (json:path not json path)
  • Using --format json without specifying the output file (JSON is printed to stdout)
  • The test-results/ directory does not exist — create it first with mkdir -p test-results

Step definitions not found

If Cucumber reports ? undefined steps, the step definition files are not being loaded. Check:

  1. The require paths in cucumber.js match where your step files are located:
// cucumber.js
module.exports = {
  default: {
    require: ['features/step_definitions/**/*.js'],
  },
};
  1. For TypeScript step definitions, use requireModule to register the transpiler:
module.exports = {
  default: {
    require: ['features/step_definitions/**/*.ts'],
    requireModule: ['ts-node/register'],
  },
};
  1. For Java, ensure the glue property points to the correct package in cucumber.properties.

Undefined steps — implement all step definitions

If you see Undefined. Implement with the following snippet: in the output, Cucumber found steps in your feature files that do not have matching step definitions. This is not a configuration error — you need to implement the missing steps.

Cucumber provides suggested code snippets in the output. Copy them into your step definition files and fill in the implementation:

# Run with --dry-run to see all undefined steps without executing tests
npx cucumber-js --dry-run

Review the output and create step definitions for every Given/When/Then step used in your feature files.