Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Learn to set up Cypress with Cucumber using cypress-cucumber-preprocessor, write Gherkin feature files, and run BDD tests on cloud.

Kailash Pathak
March 28, 2026
Cypress does not support Cucumber natively. The @badeball/cypress-cucumber-preprocessor plugin bridges the two, letting you write Cypress Cucumber BDD tests in Gherkin syntax.
Overview
Why Use Cypress With Cucumber
Cypress Cucumber is the combination of the Cypress testing framework with the @badeball/cypress-cucumber-preprocessor plugin. It lets you write BDD-style tests in Gherkin syntax and execute them as Cypress specs.
How to Set Up Cypress With Cucumber
Setting up Cypress with Cucumber requires installing the preprocessor plugin, configuring cypress.config.js, and organizing feature files with step definitions. Below are the steps:
Cypress does not support Cucumber natively. The @badeball/cypress-cucumber-preprocessor plugin bridges the two tools.
Here is how the architecture works:
In my experience, this separation keeps tests readable for non-technical stakeholders while giving testers full Cypress power.
If you are new to Cypress, start with the Cypress tutorial to understand the fundamentals before adding Cucumber.
Note: Run your Cypress tests in parallel on cloud. Try TestMu AI Today
Initialize a Node.js project and install Cypress with @badeball/cypress-cucumber-preprocessor via npm. Then configure cypress.config.js and set specPattern to target .feature files.
Make sure the following tools are installed on your machine.
Create a project folder and generate a package.json file.
mkdir cypress_Cucumber_BDD
cd cypress_Cucumber_BDD
npm init -y
Install Cypress and the Cypress Cucumber Preprocessor as dev dependencies.
npm install --save-dev cypress @badeball/cypress-cucumber-preprocessor @bahmutov/cypress-esbuild-preprocessor
Verify the installation under devDependencies in your package.json.
Here, I am registering the Cucumber preprocessor and esbuild bundler so Cypress recognizes .feature files as test specs.
const { defineConfig } = require("cypress");
const createBundler = require("@bahmutov/cypress-esbuild-preprocessor");
const { addCucumberPreprocessorPlugin } = require("@badeball/cypress-cucumber-preprocessor");
const { createEsbuildPlugin } = require("@badeball/cypress-cucumber-preprocessor/esbuild");
module.exports = defineConfig({
e2e: {
specPattern: "cypress/e2e/features/**/*.feature",
async setupNodeEvents(on, config) {
await addCucumberPreprocessorPlugin(on, config);
on("file:preprocessor", createBundler({
plugins: [createEsbuildPlugin(config)]
}));
return config;
},
},
});
Create a .cypress-cucumber-preprocessorrc.json in your project root. This file is required for the preprocessor to locate your step definition files.
{
"stepDefinitions": "cypress/e2e/step_definitions/**/*.js"
}
I organize my projects using the Page Object Model pattern.
cypress/
e2e/
features/
LoginTest.feature
SearchProductTest.feature
step_definitions/
LoginTest/
LoginTest.spec.js
SearchProductTest/
SearchProductTest.spec.js
pages/
LoginPage.js
SearchProductPage.js
Learn more about structuring tests with Cypress Page Object Model.
Create .feature files with Gherkin scenarios under cypress/e2e/features. Then write JavaScript step definition files that map each Given/When/Then step to Cypress commands.
In this feature file, I am testing a login flow using credentials from a data table.
Feature: Login into the site with valid data
Background:
Given I navigate to the Website
Scenario: Login with valid credentials
When I entered valid credential
| email | validpassword |
| testuser@test.com | Test@123 |
And User click on sign in button
Then Validate the title after login
Here, I am extending the login test by adding a product search scenario after successful login.
Feature: Login and search for a product
Background:
Given I navigate to the Website
Scenario: Login with valid credentials
When I entered valid credential
| email | validpassword |
| testuser@test.com | Test@123 |
And User click on sign in button
Then Validate the title after login
Scenario: Search the Product
When User search the product
Then Validate the product after search
| product | productaftersearch |
| VAIO | Sony VAIO |
This file covers both login and product search. Each Gherkin step maps to a Cypress command via page objects.
import { Given, When, And, Then } from "@badeball/cypress-cucumber-preprocessor";
import login from "../pages/LoginPage";
import searchProduct from "../pages/SearchProductPage";
Given("I navigate to the Website", () => {
login.enterURL();
});
When("I entered valid credential", (datatable) => {
datatable.hashes().forEach((element) => {
login.enterUserNamePassword(element.email, element.validpassword);
});
});
And("User click on sign in button", () => {
login.clickSubmitButton();
});
Then("Validate the title after login", () => {
login.verifyPageTitle();
});
When("User search the product", () => {
searchProduct.SearchProduct("VAIO");
});
Then("Validate the product after search", () => {
searchProduct.verifyProduct("Sony VAIO");
});
In LoginPage, I have encapsulated navigation, credential entry, form submission, and title verification. The should("include", "Account") call uses Cypress assertions to validate the page title.
/// <reference types="cypress" />
class LoginPage {
enterURL() {
cy.visit(
"https://ecommerce-playground.testmuai.com/index.php?route=account/login"
);
}
enterUserNamePassword(username, password) {
cy.get('[id="input-email"]').type(username);
cy.get('[id="input-password"]').type(password);
return this;
}
clickSubmitButton() {
cy.get('[type="submit"]').eq(0).click();
return this;
}
verifyPageTitle() {
// After login, the page title contains "My Account"
return cy.title().should("include", "Account");
}
}
const login = new LoginPage();
export default login;
In SearchProductPage, I have added methods for typing a product name and verifying the search result.
/// <reference types="cypress" />
class SearchProduct {
SearchProduct(searchProductName) {
cy.get('[name="search"]').eq(0).type(searchProductName);
cy.get('[type="submit"]').eq(0).click();
}
verifyProduct(productName) {
cy.contains(productName);
}
}
const searchProduct = new SearchProduct();
export default searchProduct;
Run npx cypress open to launch the GUI test runner, or npx cypress run to execute all .feature files headlessly from the terminal.
Open the Cypress test runner and select your .feature files.
npx cypress open
Select E2E Testing, choose a browser, and click the feature file to run.
Run all feature files headlessly from the terminal.
npx cypress run
All Given, When, And, and Then steps should pass for both feature files. Now, I will generate the test reports for my Cucumber Cypress tests.
To generate Cucumber reports in Cypress, install the reporter, update cypress.config.js, run tests to generate JSON, use a Node.js script to generate the HTML, and view the report.
Follow these five steps to generate a Cucumber HTML report in Cypress:
Install the reporter that will convert Cucumber JSON output into an HTML report for easy visualization.
npm install --save-dev multiple-cucumber-html-reporterUpdate your modern Cypress config file (e.g., cypress.config.js) to enable generation of Cucumber JSON files. This replaces the old cypress.json approach.
// inside cypress.config.js
module.exports = defineConfig({
e2e: {
async setupNodeEvents(on, config) {
await addCucumberPreprocessorPlugin(on, config);
return config;
},
specPattern: "cypress/e2e/**/*.feature",
},
cucumberJson: {
generate: true,
outputFolder: "cypress/cucumber-json"
}
});Run your Cypress test suite so that the Cucumber JSON reports are generated in the configured folder.
npx cypress runWrite a Node.js script to convert the generated JSON files into a Cucumber HTML report using the installed reporter.
const reporter = require('multiple-cucumber-html-reporter');
reporter.generate({
jsonDir: 'cypress/cucumber-json',
reportPath: './reports/cucumber-htmlreport.html',
metadata: {
browser: { name: 'chrome', version: 'latest' },
device: 'Local test machine',
platform: { name: 'OS', version: 'latest' }
}
});Run your HTML generation script (e.g., node cucumber-html-report.js) to create the HTML file, then open it in a browser for an interactive summary of your test results.
Note: Local execution works for development, but your CI pipeline needs to validate across Chrome, Firefox, Edge, and Safari. That requires a cloud grid.
You can use cloud testing platforms such as TestMu AI (Formerly LambdaTest) that lets you run Cypress Cucumber tests across 50+ browser and OS combinations without maintaining local infrastructure.
Install the TestMu AI Cypress CLI, generate a config file, and run your tests across multiple browsers and OS on TestMu AI's cloud.
Install the TestMu AI Cypress CLI to run Cypress UI tests on cloud.
npm install -g lambdatest-cypress-cli
Generate a lambdatest-config.json in your project root.
lambdatest-cypress init
Fill in lambdatest_auth, browsers, and run_settings in the generated file.
You can get your username and access token from the TestMu AI Profile section.
Run tests using the below command across multiple browsers on the TestMu AI platform.
lambdatest-cypress run --sync=true
To get started, head over to this guide to run Cypress test with TestMu AI.
Here are errors I have encountered frequently when setting up Cypress with Cucumber.
On one project, I spent 40 minutes debugging this before realizing the Gherkin step had a trailing space that the step definition did not. Cypress matched nothing and threw this error silently.
Fix: Copy the exact step text from your .feature file into the step definition. Do not retype it manually.
I hit this when my specPattern was set to cypress/e2e/**/*.feature but my feature files were inside a features/ subfolder. The glob did not match.
Fix: Verify that specPattern in cypress.config.js matches your actual folder structure. Use cypress/e2e/features/**/*.feature if files are nested.
This happened to me after cloning a repo where a teammate had the old cypress-cucumber-preprocessor in package.json. The import path changed completely between the old and @badeball package.
Fix: Remove the old package and install the correct one. Run npm uninstall cypress-cucumber-preprocessor && npm install --save-dev @badeball/cypress-cucumber-preprocessor.
I ran into this when two test files both defined Given("I navigate to the Website"). Cypress loaded both and could not decide which to use.
Fix: Move shared steps like navigation into a common file under step_definitions/common/. Import it in each test file instead of redefining it.
Cypress does not support Cucumber out of the box. The @badeball/cypress-cucumber-preprocessor plugin connects the two and is the only actively maintained option.
The setup requires cypress.config.js with the preprocessor plugin registered and specPattern pointing to your .feature files.
Gherkin feature files define test behavior in plain English. Step definitions map each Given/When/Then step to Cypress commands through page objects.
You can run tests locally using npx cypress open or npx cypress run. For cross-browser coverage, execute them on TestMu AI's cloud grid.
Pair your BDD tests with Cypress code coverage to measure what your feature files actually test across the application.
Explore Cypress tips and tricks for advanced techniques.
Cypress Cucumber Preprocessor npm Plugin: https://www.npmjs.com/package/cypress-cucumber-preprocessor
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance