TLDR; Nightwatch now has a new integrated test runner for Cucumber.js. Check the sample code here.

A brief introduction

Behaviour-driven Development (BDD)

Behaviour-driven Development is a software development technique that has evolved from TDD (Test-driven Development), an approach or programming practice where the developers write new code only when the automated test case fails. BDD encourages teams to use concrete examples to formalize a shared understanding of how the application should behave between various tech and non-tech teams. Tests are more user-focused and based on the system's behaviour. In BDD, “Given-When-Then” is the proposed approach for writing test cases.

Cucumber.js and Nightwatch

Cucumber is an Open Source framework that supports BDD using human language syntax and uses Gherkin as the parser. Cucumber is implemented in most mainstream programming languages, including JS. Nightwatch recently introduced the new integrated test runner for Cucumber.js in the 2.0 alpha release. No other plugins are necessary except the Cucumber library itself with this new update. In this post, we'll write and run some BDD tests to verify the search results of a museum page using Cucumber.js and Nightwatch.

đź’ˇ
You can read more about Cucumber and BDD here.

Getting Started

  1. Install Nightwatch, Cucumber and the driver for the browser you want to test. Ensure that the browser driver version is the same as your local browser.
npm i @cucumber/cucumber nightwatch chromedriver --save-dev

2. Set Cucumber as the test_runner in the nightwatch.conf file.

{
  test_runner: {
    type: 'cucumber',
    options: {
      feature_path: '*/*.feature',
      ...
    }
  src_folders: ['features/step_definitions'],
  ...
}
nightwatch.conf

You can read more about configuring Cucumber with Nightwatch.

Writing the BDD tests

Cucumber uses the Gherkin syntax to create human-readable tests. Gherkin uses a set of special keywords to give structure and meaning to executable specifications. Let's create a features/rijksmuseum.feature and write some tests to search inside the Rijksmuseum website.

Feature: Rijksmuseum Search
Background: Goto website
  Given I open the Rijksmuseum page
  And I dismiss the cookie dialog
  Then the title is "Rijksmuseum Amsterdam, home of the Dutch masters"

We'll write some Background that gets executed before every scenario. In this case, we open the museum website, close the popup, and verify the page's title.

Scenario 1

@search @nightwatch
Scenario: Searching for Night watch
  Given I search "night watch"
  Then Body contains "Operation Night Watch"
  Then Body contains "The Night Watch, Rembrandt van Rijn, 1642"

We have two tags here, namely search and nightwatch so that we can run tests based on tags. This scenario searches for “night watch” on the museum search page and verifies the search results contain “Operation Night Watch".

Scenario 2

@search @cucumber
Scenario: Searching for cucumber
  Given I search "cucumber"
  Then Body contains "Muskusroos (Rosa moschata) en komkommer (Cucumis sativus)"

These scenarios are very clear and use simple human language. The next step is to define what each of these steps means to the automated tests.

Using Nightwatch behind the scenes

Inside the features/step_definitions/rijksmuseum.js file, let's write definitions for the steps. Let's start with opening the museum page.

const {Given, Then, When} = require('@cucumber/cucumber')

Given('I open the Rijksmuseum page', function() {
  return browser.navigateTo('https://www.rijksmuseum.nl/en')
});

As you notice, we have access to the Nightwatch's browser object inside our definitions file. This access is enabled because of the new 2.0 update. We also set the src_folders: ['features/step_definitions'] in the config. Cucumber provides a way to write Cucumber Expressions, an alternative to Regular Expressions, with a more intuitive syntax.

When('I search {string}', function(searchTerm) {
  browser.click('a[aria-label="Search"]')

  return browser.waitForElementVisible('#rijksmuseum-app')
    .setValue('input.search-bar-input[type=text]', [searchTerm, browser.Keys.ENTER])
})

Nightwatch has a built-in extendable assert/verify library with the same methods, which perform assertions on elements.

Then('the title is {string}', function(title) {
  return browser.assert.titleEquals(title)
})

Running the tests

Nightwatch automatically detects and configures the test runner based on the installed driver. Since we're manually adding the config, let's set the default test_setting in the nightwatch.conf file. You can read more about the default config. The following snippet shows a simple setting for running it in chrome. For more information about default settings, you can read the test environments docs and the config docs.

  test_settings: {
    default: {
      desiredCapabilities: { browserName: 'chrome' },
      webdriver: { start_process: true },
    },
  },
nightwatch.conf

Let's run the Nightwatch tests.

npx nightwatch

You can add more parallels to the test with --parallel 2 flag. Alternatively, you can run specific tests using the cucumber tags flag --tags @search. You can check the configuration from the Nightwatch examples repo and the Developer Guide.

Conclusion

We've covered the basics of BDD testing and how to write your first test using Cucumber and Nightwatch, thanks to the new integrated test runner in the 2.0 release. So update your package now and start using Cucumber.


We Love Open Source - BrowserStack
BrowserStack offers free web and mobile testing for open source projects. Test your web and mobile apps on our Real Device Cloud. Apply with project details to qualify