It runs on both Node.js and modern web browsers.
Cucumber.js is still a work in progress. Here is its current status.
|Core (scenarios, steps, mappings)||Done|
|Command-line interface||Done1, 2|
|Scenario outlines and examples||To do|
|Stats collector||To do|
|Step argument transforms||To do|
|Wire protocol||To do|
- Not certified by Cucumber TCK yet.
- Considered for removal from Cucumber TCK.
- Missing 'matches' attributes. Simple wrapper for Gherkin's
JsonFormatterpending porting of:
in Gherkin itself.
- Will be certified by Cucumber TCK.
Cucumber.js is tested on:
- Node.js 0.6, 0.8 and 0.10.0 (see CI builds)
- Google Chrome
There are plans to have CI builds on browsers too.
Cucumber.js is available as an npm module.
Install globally with:
$ npm install -g cucumber
You may also define cucumber.js as a development dependency of your application by including it in a package.json file.
Then install with
npm install --dev
Features are written with the Gherkin syntax
# features/myFeature.featureFeature: Example featureAs a user of cucumber.jsI want to have documentation on cucumberSo that I can concentrate on building awesome applicationsScenario: Reading documentationGiven I am on the Cucumber.js GitHub repositoryWhen I go to the README fileThen I should see "Usage" as the page title
.js) and CoffeeScript (
.coffee) source files are supported.
World is a constructor function with utility properties, destined to be used in step definitions:
// features/support/world.jsvar zombie = require'zombie';var World =thisbrowser = ; // this.browser will be available in step definitionsthisbrowservisiturl callback;;callback; // tell Cucumber we're finished and to use 'this' as the world instance;exportsWorld = World;
It is possible to tell Cucumber to use another object instance than the constructor:
// features/support/world.jsvar zombie = require'zombie';var WorldConstructor =thisbrowser = ; // this.browser will be available in step definitionsvar world =thisbrowservisiturl callback;;callbackworld; // tell Cucumber we're finished and to use our world object instead of 'this';exportsWorld = WorldConstructor;
All step definitions will run with
this set to what is known as the World in Cucumber. It's an object exposing useful methods, helpers and variables to your step definitions. A new instance of
World is created before each scenario.
Step definitions are contained within one or more wrapper functions.
Those wrappers are run before executing the feature suite.
this is an object holding important properties like the
Then() functions. Another notable property is
World; it contains a default
World constructor that can be either extended or replaced.
Step definitions are run when steps match their name.
this is an instance of
// features/step_definitions/myStepDefinitions.jsvarthisWorld = require"../support/world.js"World; // overwrite default World constructorthisGiven/^I am on the Cucumber.js GitHub repository$/// Express the regexp above with the code you wish you had.// `this` is set to a new this.World instance.// i.e. you may use this.browser to execute the step:thisvisit'' callback;// The callback is passed to visit() so that when the job's finished, the next step can// be executed by Cucumber.;thisWhen/^I go to the README file$/// Express the regexp above with the code you wish you had. Call callback() at the end// of the step, or callback.pending() if the step is not yet implemented:callbackpending;;thisThen/^I should see "" as the page title$/// matching groups are passed as parameters to the step definitionvar pageTitle = thisbrowsertext'title';if title === pageTitlecallback;elsecallbackfail"Expected to be on page with title " + title;;;moduleexports = myStepDefinitionsWrapper;
It is also possible to use simple strings instead of regexps as step definition patterns:
thisThen'I should see "$title" as the page title'// the above string is converted to the following Regexp by Cucumber:// /^I should see "([^"]*)" as the page title$/var pageTitle = thisbrowsertext'title';if title === pageTitlecallback;elsecallbackfail"Expected to be on page with title " + title;;
'I have $count "$string"' would translate to
/^I have (.*) "([^"]*)"$/.
Hooks can be used to prepare and clean the environment before and after each scenario is executed.
To run something before every scenario, use before hooks:
// features/support/hooks.js (this path is just a suggestion)varthisBefore// Just like inside step definitions, "this" is set to a World instance.// It's actually the same instance the current scenario step definitions// will receive.// Let's say we have a bunch of "maintenance" methods available on our World// instance, we can fire some to prepare the application for the next// scenario:thisbootFullTextSearchServer;thiscreateSomeUsers;// Don't forget to tell Cucumber when you're done:callback;;;moduleexports = myHooks;
The before hook counterpart is the after hook. It's similar in shape but is executed, well, after every scenario:
// features/support/after_hooks.jsvarthisAfter// Again, "this" is set to the World instance the scenario just finished// playing with.// We can then do some cleansing:thisemptyDatabase;thisshutdownFullTextSearchServer;// Release control:callback;;;moduleexports = myAfterHooks;
It's also possible to combine both before and after hooks in one single definition with the help of around hooks:
// features/support/advanced_hooks.jsthisAround// "this" is - as always - an instance of World promised to the scenario.// First do the "before scenario" tasks:thisbootFullTextSearchServer;thiscreateSomeUsers;// When the "before" duty is finished, tell Cucumber to execute the scenario// and pass a function to be called when the scenario is finished:runScenario// Now, we can do our "after scenario" stuff:thisemptyDatabase;thisshutdownFullTextSearchServer;// Tell Cucumber we're done:callback;;;;moduleexports = myAroundHooks;
Hooks can be conditionally elected for execution based on the tags of the scenario.
// features/support/hooks.js (this path is just a suggestion)varthisBefore"@foo" "@bar,@baz"// This hook will be executed before scenarios tagged with @foo and either// @bar or @baz.// ...callback;;;moduleexports = myHooks;
Cucumber.js includes a binary file to execute the features.
If you installed cucumber.js globally, you may run it with:
You may specify the features to run:
$ cucumber.js features/my_feature.feature
And require specific step definitions and support code files with the --require option:
$ cucumber.js features/my_feature.feature --require features/step_definitions/my_step_definitions.js
If you installed Cucumber locally or with
npm install --dev, you'll need to specify the path to the binary:
Note to Windows users: invoke Cucumber.js with
cucumber-js instead of
cucumber.js. The latter is causing the operating system to invoke JScript instead of Node.js, because of the so-called file extension.
A few example apps are available for you to browse: