# How to write ATDD tests with cucumber-js, protractor and typescript

ATDD (Acceptance Test Driven Development) has been around for a while now. I use it quite a lot on projects that I work on. It helps me and others translate requirements into automated tests with the minimum amount of ceremony. We can talk to users about what they want and write that down in a format that they understand and we can automate.

One of the ways in which I use ATDD is with AngularJS. There is an end-to-end testing tool for AngularJS called Protractor that supports writing ATDD tests using a testframework called cucumber-js. It works pretty well with just javascript, but since we use Typescript a lot more now I figured, why not use typescript for cucumber tests as well? <!-- more -->

## What is cucumber and why should I care?

For those that don't know cucumber or ATDD for that matter. Cucumber is framework that allows you to write feature files. A feature file looks like this:

The idea behind ATDD is that you define acceptance tests in a readable format and automate them using code so that you don't have to execute them manually everytime you want to validate the functionality of your application.

Using a readable format for your users helps you create a common understanding of what the application does for the user. Automating these specs into runnable tests closes the gap between the requirements and the tests. Often times people write specs and create a separate set of tests. The problem with this is that the tests tend to drift away from the original spec. This causes bugs that could easily be avoided if you make the specs the tests.

## Setting up cucumber with protractor

In order to write acceptance tests for Angular 2 or AngularJS you need to use protractor. Protractor is a tool that links your tests to a webdriver which ultimately links your tests to a browser. This is useful since you can now navigate to a page in the application and communicate with the DOM. That way you can validate your app by querying if the right HTML elements were shown and much more.

To set protractor up you need to install the following NPM packages on your machine:

• webdriver-manager
• protractor

You can install these with the following command:

Make sure that you update the webdriver-manager after you installed it by running

This will download the proper webdriver files for you so you can start running tests against the various supported browsers such as IE, Chrome and FireFox.

Next create a new protractor configuration file in your angular project.

The file should point to the feature files in your project. I put those in the features folder, but you can place them somewhere else if you like. Next you need to set the framework to custom and point protractor to the cucumber-js framework using the frameworkPath setting.

Make sure that you install the protractor-cucumber-framework as part of your project using the following command:

Check your configuration by executing protractor protractor.conf.js. If you have a feature file in your project you should see protractor spin up a browser and spit out a bunch of text on the console about your feature file. This usually should involve a couple of green and yellow lines of text. The green lines show steps in the feature files that were executed. The yellow lines show steps that aren't implemented yet.

## Automating feature files with typescript

The cucumber-js framework is meant to be used with Javascript. In order to do this you need to write step definitions in javascript files that look like this:

You include them in the protractor config file by specifying a setting called cucumberOpts that tells the cucumber framework to require your step definition javascript files.

I found that javascript is good, but quite annoying to work with since there's so much crap in the syntax to deal with. People do the weirdest things to their javascript code. Cucumber-js sadly isn't an exception to that rule.

Typescript offers a much better way of defining step definitions for cucumber-js. But you have to do a little work for it to function properly.

First you need to install the ts-node and cucumber-js-tsflow packages in your project using the following command:

Next you need to modify the protractor configuration so that it includes the following cucumberOpts settings:

This configures cucumber so that it looks for step definitions in the features/step_definitions folder and tries to load the typescript files directly from there. The problem is that it can't load typescript files under normal circumstances. However, you can specify a custom compiler for the cucumber framework. This is where ts-node comes in. When you configure cucumber-js to use the typescript interface from ts-node it is capable of loading the step definitions.

Time to write some step definitions in typescript:

This looks way easier to read and I can assure you it's much more ergonomic to write. And luckely it is not much work to set up in the end.

Willem Meints

AI Fanatic, Technical Evangelist, Microsoft MVP