How to write E2E tests in plain text using Cucumber.js
Tags: webdev, cucumberjs, beginners, javascript
Published: 2022-01-12 05:56:55

**End-to-End (E2E) Testing** is a testing methodology used in software development life cycle (SDLC) to test the functionality of an application deployed as a complete system. This simulates real world user scenarios starting from frontend application, and verifies the application works as expected. After completion of this test, not only the frontend application but all the other sub-systems are validated as well.


![E2E Testing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmfdvcdfcfhucnpdwjx3.png)

There are some advance, developer friendly Javascript based E2E Testing Frameworks such as [Cypress](https://www.cypress.io/), [Protractor](https://www.protractortest.org/#/) and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro). 

But [Cucumber](https://cucumber.io/) is well-known for its native support for **Behavior Driven Development (BDD)**. 

## What is Behavior Driven Development (BDD)?

Behavior Driven Development (BDD) is an approach that defines the behavior of an application through examples of plain text ([gherkin syntax](https://cucumber.io/docs/gherkin/reference/)). At the beginning of the development, this human readable document defines the application specifications, but later it can be used as an executable that runs the E2E tests. 

![Behavior Driven Development (BDD)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zz17sjatdgl2e5412qg.png)

This powerful approach helps the cross functional team (marketing, product owners, developers) to create a shared understanding of the application features and minimizes the gap between technical and non-technical team members.

More information about BDD
- https://cucumber.io/docs/bdd/
- https://cucumber.io/blog/bdd/getting-started-with-bdd-part-1/ 

Aforementioned feature specifications are written using gherkin syntax with familiar **Given**, **When**, **Then** format. 

```gherkin
Feature: Add Todo
  Scenario: add simple todo
    Given I load the TodoApp
    When I add new todo called "Pay rent"
    Then I should see a "pending" todo called "Pay rent"
```

Like any other E2E Testing Framework, Cucumber.js also expects an assertion library such as [assert](https://nodejs.org/api/assert.html) or [chai](https://www.chaijs.com/) and WebDriver for browser automation such as [selenium-webdriver](https://www.selenium.dev/documentation/overview/).  

In this post, I will focus on 
- Installing Javascript version of Cucumber ([cucumber.js](https://github.com/cucumber/cucumber-js)) on a simple Todo App written in React. 
- Write some feature specifications in gherkin format
- Execute those feature specifications as E2E tests. 

Our final application and e2e tests configuration would look like following. 

![Todo App with E2E](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2opjrymboup72uj3w52.png)

You can also refer to my [github project](https://github.com/PahanPerera/simple-todo-app-with-bdd) that has everything covering in this post. 

Let's get started...! 

### Create a simple web app and install cucumber.js

You can use any web application that you have for this or create a simple app like my [simple todo app](https://github.com/PahanPerera/simple-todo-app-with-bdd).

![Screenshot of the TodoApp](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8orr3qkhhqj6y77j8whw.png)

#### Install dependencies

```
yarn install -D @cucumber/cucumber chromedriver selenium-webdriver
```
You might need to install an assertion library that you prefer. But to keep things simple, I am using NodeJS inbuilt [assert](https://nodejs.org/api/assert.html) library.

Update the scripts in package.json to run the tests as well

```json
"scripts": {
    ...
    "e2e": "cucumber-js e2e-tests"
},
```

Also if you want to define advance configurations you can create a [`cucumber.js`](https://github.com/PahanPerera/simple-todo-app-with-bdd/blob/main/cucumber.js) file.

Also make sure the app is running at `http://localhost:3000`, so that our e2e tests can run against that. 

### Write a Gherkin based feature specification

Inside the `e2e-tests` folder, add the following [`addTodo.feature`](https://github.com/PahanPerera/simple-todo-app-with-bdd/blob/main/e2e-tests/addTodo.feature) file. (`.feature` extension is important for the cucumber.js)

```gherkin
Feature: Add Todo
  Scenario: add simple todo
    Given I load the TodoApp
    When I add new todo called "Pay rent"
    Then I should see a "pending" todo called "Pay rent"
``` 

### Write Step Definitions

Step definitions are a code that you write to help converting gherkin based feature specification into a machine readable executables. For an example when you say `When I add new todo called "Pay rent"`, step definitions explain what need to be done in the application. 

Basically it will

1. Find the input field to enter the todo
2. Type "Pay rent" in that input field
3. Find the button which saves the todo
4. Click that button

In High level there are two steps

#### Configure the WebDriver

You need to configure a WebDriver so that your web application can be manupilated by the test scripts. In this example I am installing `chromedriver` which provides the chrome driver as a NodeJS Module (NPM). 

Web Driver's `driver` object can be initiated as below.

```js
this.driver = await new Builder()
  .forBrowser("chrome")
  .setChromeService(service)
  .setChromeOptions(chromeOptions)
  .build();
```

To learn more about installing drivers, you can refer [this](https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/). 

#### Write the step definitions

You can create a [`steps.js`](https://github.com/PahanPerera/simple-todo-app-with-bdd/blob/main/e2e-tests/lib/steps.js) file inside the `e2e-tests/lib` folder 

```js
When("I add new todo called {string}", async function (todoText) {
  // 1. Find the input field to enter the todo
  const input = await this.getAddTodoInput();
  // 2. Type "Pay rent" in that input field
  await input.sendKeys(todoText);
  // 3. Find the button which saves the todo
  const btn = await this.getAddTodoButton();
  // 4. Click that button
  await btn.click();
});
```
As you can see, step definition function can be parameterized, providing ability to create generic function that works for multiple cases. 

Also if you see, there are some utility functions like `this.getAddTodoInput()` that are used to detect the UI components within your web application. You can create a [`world.js`](https://github.com/PahanPerera/simple-todo-app-with-bdd/blob/main/e2e-tests/lib/world.js) with those utility function. 

```js
  async getAddTodoInput() {
    return this.driver.findElement(By.name("addTodoInput"));
  }

  async getAddTodoButton() {
    return this.driver.findElement(By.id("addTodoBtn"));
  }

  async getTodoCountText() {
    return this.driver.findElement(By.id("todoCountText"));
  }
```

To understand more about the `steps.js` and `world.js` please refer to [this](https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/world.md). 

My goal here is to highlight some of the important areas that you need to focus on integrating cucumber.js to your next web application. Since this might be little confusing to a beginner, I really encourage you to refer to the sample application. 

https://github.com/PahanPerera/simple-todo-app-with-bdd

This is how those low level components are stitching together to run the e2e tests

![Todo App E2E Low Level Components](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39xhoazau81wdbqx6hto.png)

Finally you can run the e2e tests
```sh
yarn e2e
```

![E2E Test Run logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbvt2f4a1xvmp8us89yz.png)

If you configure the HTML reporting, you can see a e2e-report.html file generated as well

![E2E Test Report](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7a40xuk5g3a6sfgophec.png)

## Conclusion

BDD style E2E Tests might not be a fully convenient approach for a very technical developer, But it helps when you work in cross functional team. Also implement this approach in a real world software development life cycle can be more tricky than it appears. 

Overall I think this is a very innovative concept that brings all the team members together and helps improving the productivity as well. 

In this post, I roughly touched on the initial implementation that helps you to get started with your BDD style E2E Tests with Cucumber.js, Gherkin and Selenium Web Driver. 

All the points that we discussed in this, can be found in this sample repo. 
https://github.com/PahanPerera/simple-todo-app-with-bdd

❤️ Appreciate your feedback and thank you for reading...