cucumber-boilerplate: a WebdriverIO and Cucumber starting point for BDD browser tests
Boilerplate project to run WebdriverIO tests with Cucumber
At a glance
- What is it?
- The WebdriverIO cucumber-boilerplate is a starting project that pairs WebdriverIO with Cucumber so end to end browser tests can be written in Gherkin rather than in code. It ships more than 150 predefined steps, environment specific configuration files and tag filtering, and it deliberately leaves browser infrastructure to you.
- Who is it for?
- cucumber-boilerplate suits a team that has decided to write browser tests in Gherkin for non developers to read and wants the step library, config layering and tag filtering already in place, and it does not suit a team that has no browser infrastructure yet, since the readme is explicit that the project does not cover setting up a test environment.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the boilerplate actually gives you
The readme calls this a boilerplate project to run WebdriverIO tests with Cucumber, and its purpose is stated in the first paragraph: instead of writing complicated test code that only developers can understand, Cucumber maps an ordinary language to code and allows you to start with the test process in the early stages of your product development.
That is the argument for the whole approach, and it is the argument a product manager or a QA person would recognise. A Gherkin file reads like a description of behaviour, and the person who writes it does not need to know anything about WebdriverIO.
The concrete contents are the useful part. The feature list claims a super simple setup, full integration with WebdriverIO, over 150 predefined steps that cover almost everything you need, easy integration with cloud services like Sauce Labs, integration of WebdriverIO's multiremote functionality, and the ability to run tests in parallel.
The step library is the substance. Over 150 predefined steps means the common interactions with a page are already written, and a new test is mostly an assembly of phrases like opening a URL, setting an input field and pressing a key. The repository layout supports that: a src/ directory with a features folder and a steps folder, a test/ directory, a demo-app/ directory that provides a page to test against, and the configuration files at the top level.
There is also a src/steps split into given, when and then, which is the natural Cucumber organisation and also makes it obvious where to put a new step definition. The steps use regular expressions, and the readme explains the mechanism: everything within a captured group is appended to the callback, and the last argument is always a callback function you call when the step is done. The browser and the WebdriverIO instance are reachable through the browser object, and assertions use expect-webdriverio, WebdriverIO's embedded assertion library.
Installation expects you to bring a browser yourself
The requirements section is short and it contains the constraint that decides whether this project is for you.
Node version 14 or higher is required. So is a preconfigured Selenium Grid, a preinstalled browser driver, or a cloud provider account. The readme then spells out what the project does not do: it does not cover setting up a proper test environment, you need to download the specific browser driver yourself and run the prior starting tests, or use a cloud provider like SauceLabs.
That is a deliberate boundary rather than an oversight. A boilerplate that shipped a browser installation would be tied to a specific driver version and would break whenever that version moved. Leaving it to you means the boilerplate stays small.
The package manager recommendation is worth following. Although the project works fine with npm, the readme recommends Yarn of version 1.0.0 or newer because of its speed and solid dependency locking, and the guide uses yarn throughout while saying you can substitute npm if that is what you use.
The quick start has a step that is easy to skim past. You download the latest stable release or clone the git repository, then copy the files into your project into a directory like /integrationtests, with the note that the hidden files matter. That hidden files warning is the kind of detail that costs an afternoon if you miss it, since the configuration, the CI workflow and the editor settings all live in dotfiles.
There is an optional clean step, which differs by platform. On OSX and Linux you run yarn run clean. On Windows you remove the directories /.git, /.github, /demo-app and /test, remove the files .travis.yml, jest.json and wdio.BUILD.conf.js, and remove all the demo features from the /src/features directory. The Windows instructions are manual because the clean script uses a bash conditional, and the package.json shows why: the clean script is a shell one-liner with a read prompt.
Gherkin in, and the example that shows the shape
Tests are written in Gherkin syntax, which the readme describes as writing down what is supposed to happen in a real language. All test files live under ./src/features with a .feature extension, and the repository already contains some so you can see what they look like.
The sample feature file is the clearest documentation in the project.
Feature:
In order to keep my product stable
As a developer or product manager
I want to make sure that everything works as expected
Scenario: Check title of website after search
Given I open the url "http://google.com"
When I set "WebdriverIO" to the inputfield "#lst-ib"
And I press "Enter"
Then I expect that the title is "WebdriverIO - Google Search"What this shows is that the step phrasing is fixed and the values are parameters. The Given, When, And, Then structure maps onto the given, when and then folders in src/steps, and the quoted values are the captured groups. Writing the file does not require knowing the WebdriverIO call that sets an input field, which is the whole point of the exercise.
The readme walks through what the test does, and it is a fair description of the shape of any browser test: it opens the browser, navigates to google.com and checks that the title contains the search query after doing a search.
The other Gherkin features in the readme cover the parts of the workflow people usually get wrong. Tags go before the Feature line, and a Pending tag either on a Feature or on a single Scenario marks failing or unimplemented tests as skipped, which is how you land a failing test on a branch without blocking the run. Block comments use the triple hash form and can sit above a feature.
One small inconsistency to note. The readme refers to step definitions in ./src/steps and the feature files in ./src/features, but the command for running a single feature points at ./test/features/select.feature. The repository root also holds both a src/ and a test/ directory, so which path holds your features in practice is worth checking in your checkout before you write anything.
The scripts tell you how the pieces fit together
The package manifest is where the whole project structure becomes concrete, and it is worth reading line by line.
There are seven scripts. The clean script is the interactive one. The test script is run-s test:*, which means it runs every script whose name begins with test: in sequence, and there are three of them. test:lint runs eslint over src and test. test:unit runs jest with the jest.config.cjs config and the --detectOpenHandles flag. test:features runs wdio run against wdio.BUILD.conf.ts. And wdio is the same runner invocation, exposed so you can call it directly.
Two details are worth calling out. The lint step covers src TypeScript files and test JavaScript files, with a negated pattern that excludes setup.js, so the setup file is allowed to break the rules. And --detectOpenHandles makes Jest report handles that are still open after the tests finish, which is the difference between a test run that exits and a test run that hangs, and it is the kind of flag a boilerplate should set for you.
The dependency list shows the WebdriverIO version being used, which is 9.1.2 across @wdio/cli, @wdio/config, @wdio/cucumber-framework, @wdio/globals, @wdio/local-runner, @wdio/spec-reporter and @wdio/static-server-service, with the cucumber framework adapter installed alongside. The static server service is what serves the demo app during a local run, and the local runner is what makes parallel execution possible.
The project is an ES module, the type field in the manifest is set to module, and the tooling is TypeScript aware with a tsconfig.json, a @typescript-eslint parser and plugin, eslint 8 with the airbnb-base config, and the eslint-plugin-wdio rules.
One mismatch is worth flagging before you start. The manifest version is 2.0.0 and the scripts point at wdio.BUILD.conf.ts, while the readme's prose still talks about WebdriverIO alpha v8 and a wdio.conf.js file, and the documented configuration examples are JavaScript. The repository top level holds wdio.conf.ts and wdio.BUILD.conf.ts, so the readme's file names are one generation behind the code.
Layered configuration and running one thing at a time
The configuration section describes a scheme for having more than one environment, and it is a good pattern to copy into other test suites.
The idea is that wdio.conf.js holds everything general, such as the mocha options, and acts as the default values. For each environment you create a new file following a naming scheme of wdio.<ENVIRONMENT>.conf.js, and the environment specific file is merged into the default one, overwriting the values you set.
The example is a staging config that changes only the baseUrl.
var config = require('./wdio.conf.js').config;
config.baseUrl = 'http://staging.example.com'
exports.config = config;Note the require of the default config, the mutation of the baseUrl property, and the re-export. The whole environment specific file is three meaningful lines, which is what makes the pattern cheap to apply.
To use it you pass the config file as the first parameter to the runner.
$ yarn run wdio wdio.STAGING.conf.jsThat same mechanism handles running a single feature or a subset of tests. A single spec is run with npx wdio wdio.conf.js --spec ./test/features/select.feature, and a tagged subset with the cucumber tag expression parameter, where the example runs tests with @Tag or @AnotherTag.
$ npx wdio wdio.conf.js --cucumberOpts.tagExpression='@Tag or @AnotherTag'The tag expression syntax is not this project's own, the readme points at the Cucumber.js documentation for further tag options. The local server and the runner are two separate commands, since the readme says to start the local web server with yarn run test and then to run the tests by calling the WDIO runner with yarn run wdio. That separation matters in CI, where the server has to be up before the runner connects to it.
Where the boilerplate runs out
The limitations are the obvious ones for a starting project, and they are worth stating before anyone copies this into a production suite.
The first is infrastructure. You need a browser driver, a Selenium Grid or a cloud account before anything runs, and the readme is explicit that the project does not cover setting up a test environment. The demo-app directory exists so that the sample tests have something to hit locally, and in a real project that target is your own application.
The second is the step library's rigidity. The 150 or so predefined steps are a starting vocabulary, and the readme says you might need extra snippets better aligned with your aims, with the step definitions living in ./src/steps and split into given, when and then. The mechanism for that is regular expressions, which the readme praises for its flexibility, but the flip side is that a heavily parameterised step set becomes a mini language that someone on your team has to maintain, and a step phrased too loosely will match in ways you did not intend.
The third is the version drift visible in the repository. The manifest is at 2.0.0 with WebdriverIO 9.1.2 and TypeScript configuration files, while the readme describes WebdriverIO alpha v8, uses wdio.conf.js in its examples and gives a yarn run wdio command against a different config file name. The listed releases stop at v1.3.2 from 2017, so the release tags do not describe the current state of the manifest. The last push was on 2026-10-11, so the repository is being worked on, but the documentation and the code are at different generations and you will hit that.
On the alternative, the difference in approach between this and a plain WebdriverIO test suite is the layer between the test and the browser. Writing WebdriverIO directly gives you maximum control and no vocabulary to maintain, and every assertion is visible in the test file. Going through Gherkin and Cucumber costs you a step definition layer and some indirection, and buys you tests that a product manager can read and write. The trade is worth it when the people who define what should be tested are not the people who write the automation, and it is not worth it when they are the same person. There is also the middle path of using the WebdriverIO step definitions without Cucumber, which keeps the browser level control and drops only the Gherkin syntax, and that is what a lot of teams end up with once the boilerplate has been customised.
Editorial conclusion
cucumber-boilerplate suits a team that has decided to write browser tests in Gherkin for non developers to read and wants the step library, config layering and tag filtering already in place, and it does not suit a team that has no browser infrastructure yet, since the readme is explicit that the project does not cover setting up a test environment. Before you adopt it, decide where your browser driver or Selenium Grid will come from, and check the version of WebdriverIO the package pins, because the readme still describes an alpha v8 setup while the manifest now depends on the 9.1.2 packages.
Frequently asked questions
What is the WebdriverIO cucumber-boilerplate?
It is a boilerplate project to run WebdriverIO tests with Cucumber, bringing BDD to JavaScript. It ships over 150 predefined steps, per environment configuration files, tag filtering and support for parallel runs and multiremote.
What do I need before the cucumber-boilerplate will run?
Node version 14 or higher, and a preconfigured Selenium Grid, a preinstalled browser driver or a cloud provider account. The readme states the project does not cover setting up a proper test environment, so you download the browser driver yourself.
How do I run a single feature file with the cucumber-boilerplate?
Use the WDIO runner with the spec option, for example npx wdio wdio.conf.js --spec ./test/features/select.feature. The readme points out that the WDIO runner uses the configuration file wdio.conf.js by default.
How do I set up different configs per environment?
Keep the general settings in wdio.conf.js and create a file named wdio.<ENVIRONMENT>.conf.js for each environment, requiring the default config, changing the values you need and exporting the result. You then pass that file as the first parameter to the runner.
Where do I add my own step definitions in the cucumber-boilerplate?
In ./src/steps, which is split into given, when and then. You define the step with a regular expression, where captured groups are appended to the callback, and the last argument is the callback you call when the step is done.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/webdriverio-cucumber-boilerplate)Was this useful?