Cover image from What I’ve learned about cucumber js

What I’ve learned about cucumber js

March 29, 2018

CucumberJS is a NodeJS implementation of a test runner which is powered by the Gherkin syntax. It’s integration with our team workflow has been a boon to clarity of purpose for stories in firstly SCRUM and now KANBAN. Here I will share some of things we’re doing and the benefits we reap.

When writing a story the team gathers around a screen and we work on a shared text. Straight away this increases collaboration and removes a lot of later disagreements around ‘I thought we said we would do X after Y’. The Gherkin story states in a language somewhere between pseudo-code and a more traditional Agile story what is going to happen. This post is not an introduction to Gherkin syntax, you can read more about it here.

The following is the format we generally use:

Feature: As a blogger I would like to make blog posts So I can share knowledge

Scenario: Write post with content Given I have content When I enter the content And I publish the content Then the content is published

The following are some key takeaways we have ascertained from this approach.

Keep the number of features small and user focused

A feature is something that the user uses. There is very little to be gained by implementing features or scenarios that the user can not directly be cognisant of because they will have no testable aspect. Rather, try to discover what the benefit to the user is of the story and find where that can be most easily integrated into an existing feature if one exists. This should reduce excess feature files or excessively large feature files. If a story covers only technical detail that does not directly impact the user then maybe it would be better suited to unit and functional tests.

 

Establish a grammer which utilises parameters

Early in the project try to create a grammer. Preferably one which accepts parameters. In future these can then be re-used to test other scenarios and increase the speed of testing. For example the following snippet improves on the first one and can be re-used to test different content.

Scenario: Write post with content Given I have the following content | title | body | | —– | —- | | My Post | The post was long and full of points | When I enter the content And I publish the content Then the content is published

Access the scenario name to customise any output

This is a pretty simple one. The before step exposes a reference object. From this object the name of the current scenario can be retrieved. I can then use this reference to persist items with unique names for the particular run.

const { defineSupportCode } = require('cucumber');

defineSupportCode(function ({ Before, After }) {
    Before(function (stepRef) {
        this.stub = stepRef .pickle.name .toLowerCase() .replace(/ /g, '-');
    });
});

Export an image or logs when debugging selenium

When debugging selenium based projects I find two sources of information very handy. The console logs from the previous browser session and a screenshot of the browser as it was after the test had run. This can be achieved using the After hook. The code below assumes that the driver variable is already configured as a reference to an instance of Selenium WebDriver or a similar library.

const { defineSupportCode } = require('cucumber');
const logging = require('selenium-webdriver/lib/logging');
const fs = require('fs');

defineSupportCode(function ({ Before, After }) {
    After(function () {
        // Print whatever logs exist for this session
        driver.manage().logs().get(logging.Type.BROWSER)
            .then((entries) => {
                entries.forEach((entry) => {
                    console.log('\[%s\] %s', entry.level.name, entry.message);
                });
                // Save a screenshot of the browser
                driver.takeScreenshot()
                    .then((pngString) => {
                        fs.writeFileSync(\`${this.stub}.png\`, pngString, 'base64');
                    });
            });
    });