Tuesday, June 27, 2017

BDD in JavaScript: Getting Started with Cucumber and Gherkin

BDD in JavaScript: getting Started with Cucumber and Gherkin

By now, everyone has heard about Test Driven Development (TDD), and the benefits that this can have on your product and your development lifecycle. It's a no-brainer really. Every time you write a test for a piece of code, you know that code works. And, what's more, you will know in the future if that code breaks.

Behavior Driven Development (BDD) is an extension to this concept, but instead of testing your code you are testing your product, and specifically that your product behaves as you desire it to.

In this article, I'm going to show you how to get up and running with Cucumber, a framework that runs automated acceptance tests written in a BDD style. The advantage of these tests is that they can written in plain English and consequently understood by non-technical people involved in a project. After reading, you will be in a position to decide if Cucumber is a good fit for you and your team and to start writing acceptance tests of your own.

Ready? Then let's dive in.

BDD vs TDD — so, What's the Difference?

Primarially in the way that tests are structured and written.

In a TDD setting, the tests are written, maintained and understood by the developers who wrote the code they are testing. It might well be that nobody else ever needs to read the tests at all, and that's fine.

In a BDD setting, the tests need to be understood by a lot more than just the developer writing the functionality. There are many more stakeholders who have an interest that the product behaves as it should.
These might include QA people, product analysts, sales, even upper management.

This means that, in an ideal world, BDD tests need to be written in a way that anyone who understands the product will be able to pick up the tests and understand them as well.

It's the difference between:

const assert = require('assert');
const webdriver = require('selenium-webdriver');
const browser = new webdriver.Builder()
  .usingServer()
  .withCapabilities({'browserName': 'chrome' })
  .build();

browser.get('http://ift.tt/ox1Ync');
browser.findElements(webdriver.By.css('[href^="/wiki/"]'))
.then(function(links){
  assert.equal(19, links.length); // Made up number
  browser.quit();
});

And:

Given I have opened a Web Browser
When I load the Wikipedia article on "Wiki"
Then I have "19" Wiki Links

The two tests do exactly the same thing, but one is actually human readable and the other is only readable by someone who knows both JavaScript and Selenium.

This article will show you how you can implement BDD Tests in your JavaScript project, using the Cucumber.js framework, allowing you to benefit from this level of testing for your product.

What Is Cucumber / Gherkin?

Cucumber is a testing framework for behavior driven development. It works by allowing you to define your tests in Gherkin form, and makes these gherkins executable by tying them to code.

Gherkin is the Domain Specific Language (DSL) that is used for writing Cucumber tests. It allows for test scripts to be written in a human readable format, which can then be shared between all of the stakeholders in the product development.

Gherkin files are files that contain tests, written in the Gherkin language. These files typically have a .feature file extension. The contents of these Gherkin files are often referred to as simply "gherkins".

Gherkins

In a Gherkin defined test, you have the concept of features and scenarios. These are analogous to test suites and test cases in other testing frameworks, allowing for a clean way to structure your tests.

A scenario is literally just a single test. It should test exactly one thing in your application.

A feature is a group of related scenarios. As such, it will test many related things in your application. Ideally the features in the Gherkin files will closely map on to the Features in the application — hence the name.

Every Gherkin file contains exactly one feature, and every feature contains one or more scenarios.

Scenarios are then comprised of steps, which are ordered in a specific manner:

  • Given - These steps are used to set up the initial state before you do your test
  • When - These steps are the actual test that is to be executed
  • Then - These steps are used to assert on the outcome of the test

Ideally each scenario should be a single test case, so the number of When steps should be kept very small.

Steps are entirely optional. If you have no need to set anything up at all, you might have no Given steps, for example.

Gherkin files are designed to be human readable, and to give benefit to anyone involved in the product development. This includes non-technical people, so the Gherkin files should always be written in business language and not technical language. This means, for example, that you do not refer to individual UI components, but instead describe the product concepts that you are wanting to test.

An Example Gherkin Test

The following is an example Gherkin for searching Google for Cucumber.js

Given I have loaded Google
When I search for "cucumber.js"
Then the first result is "GitHub - cucumber/cucumber-js: Cucumber for JavaScript"

Straight away we can see that this test tells us what to do and not how to do it. It is written in a language that makes sense to anyone reading it, and — importantly — that will most likely be correct no matter how the end product might be tweaked. Google could decide to completely change their UI, but as long as the functionality is equivalent then the Gherkin is still accurate.

You can read more about Given When Then on the Cucumber wiki.

Cucumber.js

Once you have written your test cases in Gherkin form, you need some way to execute them. In the JavaScript world, there is a module called Cucumber.js that allows you to do this. It works by allowing you to define JavaScript code that it can connect to the various steps defined inside of your Gherkin files. It then runs the tests by loading the Gherkin files and executing the JavaScript code associated with each step in the correct order.

For example, in the above example you would have the following steps:

Given('I have loaded Google', function() {});
When('I search for {stringInDoubleQuotes}', function() {});
Then('the first result is {stringInDoubleQuotes}', function() {});

Don't worry too much about what all of this means - it will be explained in detail later. Essentially though, it defines some ways that the Cucumber.js framework can tie your code to the steps in your Gherkin files.

Including Cucumber.js in Your Build

Including Cucumber.js in your build is as simple as adding the cucumber module to your build, and then configuring it to run. The first part of this is as simple as:

$ npm install --save-dev cucumber

The second of these varies depending on how you are executing your build.

Running by Hand

Executing Cucumber by hand is relatively easy, and it's a good idea to make sure you can do this first because the following solutions are all just automated ways of doing the same.

Once installed, the executable will be ./node_modules/.bin/cucumber.js. When you run it, it needs to know where on the file system it can find all of its required files. These are both the Gherkin files and the JavaScript code to be executed.

By convention, all of your Gherkin files will be kept in the features directory, and if you don't instruct it otherwise then Cucumber will look in the same directory for the JavaScript code to execute as well. Instructing it where to look for these files is a sensible practice however, so that you have better control over your build process.

For example, if you keep all of your Gherkin files in the directory myFeatures and all of your JavaScript code in mySteps then you could execute the following:

$ ./node_modules/.bin/cucumber.js ./myFeatures -r ./mySteps

The -r flag is a directory containing JavaScript files to automatically require for the tests. There are other flags that might be of interest as well — just read the help text to see how they all work: $ ./node_modules/.bin/cucumber.js --help.

These directories are scanned recursively so you can nest files as shallowly or deeply as makes sense for your specific situation.

npm scripts

Once you have got Cucumber running manually, adding it to the build as an npm Script is a trivial case. You simply need to add the following command — without the fully qualified path, since npm handles that for you — to your package.json as follows:

"scripts": {
  "cucumber": "cucumber.js ./myFeatures -r ./mySteps"
}

Once this is done, you can execute:

$ npm run cucumber

And it will execute your Cucumber tests exactly as you did before.

Grunt

There does exist a Grunt plugin for executing Cucumber.js tests. Unfortunately it is very out of date, and doesn't work with the more recent versions of Cucumber.js, which means that you will miss out on a lot of improvements if you use it.

Instead, my preferred way is to simply use the grunt-shell plugin to execute the command in the exact same way as above.

Once installed, configuring this is simply a case of adding the following plugin configuration to your Gruntfile.js:

shell: {
  cucumber: {
    command: 'cucumber.js ./myFeatures -r ./mySteps'
  }
}

And now, as before, you can execute your tests by running grunt shell:cucumber.

Continue reading %BDD in JavaScript: Getting Started with Cucumber and Gherkin%


by Graham Cox via SitePoint

No comments:

Post a Comment