Endjin - Home

Step-by-step guide to setting up CucumberJS in Visual Studio 2015

by Matthew Adams

header-a-step-by-step-guide-setting-up-cucumberjs-p1-1024px

At endjin, we love using Gherkin, from “unit”-style tests, all the way through to Integration and User Acceptance testing. In the .NET world, we make use of SpecFlow which has great integration with Visual Studio.

With Visual Studio 2015 and its new support for npm/grunt, setting up CucumberJS for gherkin-style testing of JavaScript is pretty straightforward.

1) Add a package.json file to your project

This gives you support for npm-style package management. It works in any type of project, not just the new-style ASP.NET build system.

2) Add dependencies for cucumber, grunt and grunt-cucumber.

{
  "devDependencies": {
    "cucumber": "latest",
    "grunt": "latest",
    "grunt-cucumber": "latest"
  },
  "name": "Specs",
  "private": true,
  "version": "1.0.0"
}

Grunt-Cucumber is a simple (and easily customized) grunt execution engine for CucumberJS.

3) Add a gruntfile.js to your project

This allows you to configure grunt to execute your task

4) Add some configuration for grunt-cucumber

/*
This file in the main entry point for defining grunt tasks and using grunt plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkID=513275&clcid=0x409
*/
module.exports = function (grunt) {
    grunt.initConfig({
        cucumberjs: {
            src: 'Features',
            options: {
                steps: "Features"
            }
        }
    });

    grunt.loadNpmTasks('grunt-cucumber');
};

The src option gives the relative path to the folder containing your feature files.
The steps option gives the relative path to your step definitions.

5) Add a .feature file for your Gherkin spec, and a step-definition JavaScript file

ProjectStructure

Here’s an example feature file:

Feature: Division
  In order to avoid silly mistakes
  Cashiers must be able to calculate a fraction

  Scenario: Regular numbers
    Given I have entered 3 into the calculator
    And I press divide
    And I have entered 2 into the calculator
    When I press equal
    Then The result should be 1.5 on the screen

And the example step definitions

// features/example/example.js

module.exports = function () {
    this.Given(/^I have entered (.*) into the calculator$/, function (value, callback) {
        if (!this.valueStack) {
            this.valueStack = [];
        }

        this.valueStack.push(Number(value));
        callback();
    });

    this.Given(/^I press divide$/, function (callback) {
        if (!this.operatorStack) {
            this.operatorStack = [];
        }

        this.operatorStack.push("divide");
        callback();
    });

    this.When(/^I press equal/, function (callback) {
        var operator = this.operatorStack.pop();
        switch (operator) {
            case "divide":
                var right = this.valueStack.pop();
                var left = this.valueStack.pop();
                this.result = left / right;
                break;
        }
        callback();
    });


    this.Then(/^The result should be (.*) on the screen$/, function (result, callback) {
        if (this.result === Number(result)) {
            callback();
        } else {
            callback(new Error("Expected " + result + " actual " + this.result));
        }
    });
};

6) Build the solution

You have to do this to get the packages pulled down.

7) Open up Task Runner Explorer

Right click the gruntfile, and open Task Runner Explorer

TaskRunner

You can see the cucumberjs task in the tree, and a set of bindings for various build events.

TaskRunner2

8) Run the specs

Double click the cucumberjs node to run your specs

CucumberResults

9) Integrate with the build

If you want to, you can hook your grunt-cucumber task into the build. Right click the cucumberjs node and select Bindings->After build.

SetupBinding

This actually adds a bit of code into the top of your gruntfile.js

/// <binding AfterBuild='cucumberjs' />

Now, when you build, it will re-run your specs.

For more sophisticated build environments, you can get cucumber to spit out JSON output instead of pretty-printing, and then consume that as part of your continuous integration process.

If you enjoyed this post, please consider sharing it on social media using the buttons below. Thanks!

About the author

Matthew was CTO of a venture-backed technology start-up in the UK & US for 10 years, and is now a Founder of Endjin Ltd, which provides technology strategy, experience and development services to its clients who are seeking to take advantage of Microsoft Azure and the Cloud. You can follow Matthew on twitter.