CucumberJS Basics In Depth (Visual Studio Code Editor)

Introduction 

 
Hello friends! Today, I am going to briefly explain CucumberJs basics in Protractor. Before that, let's get to know what the Protractor is.
 

What is Protractor?

 
Protractor is a node.js framework that is built on top of Selenium Webdriver APIs. It is basically used to automate angular applications. It contains the features that are available in selenium web driver. In addition to selenium locators, we have protractor locators that are helpful to automate Angular applications.
 
Before talking about Cucumber, let's see the installation details.
  1. Jdk 1.8 needs to be installed (https://www.oracle.com/in/java/technologies/javase/javase-jdk8-downloads.html)
  2. Download the node js (https://nodejs.org/en/download/)
  3. You need to write and run scripts on editor, I am using Visual studio code editor in this article, which is open-source and popular in the market. So you can download it from (https://code.visualstudio.com/).
After installing the above required software, you can verify it using the command prompt.
 
To check the installed JDK: 
  1. java -version  
To check node js:
  1. node -v  
 
 
 After installing the VisualStudio code editor. You can also use to run the code using the terminal.
 
Create a folder in the local system Ex: "Cucumberbasics" -> Open the folder in Visual Studio code.
  1. npm init  
"init" is the main start of any program in node js. It normally use to create utility "package.json" file. Instead of creating it manually, you can use the above command.
 
It just basically ask you certain details like package name. So you can give any package name (ex: cucumberjsBasics"). Please see the below screenshot
 
 
After entering the package name, it will ask you certain details like gitversion, authorname, keywords etc. you can enter the details or you can skip by clicking on enter button.
 
Refer to the image below. You can see the package.json file generated with the details you entered. You can edit the changes in package.json file also.
 
 

Configuring CucumberJs node package

 
You can refer to the npm cucumber package installation in https://www.npmjs.com/package/cucumber
 
You can download this in VisualStudio code terminal, as shown below.
 
After downloading in the left pane you can see "node_modules" folder. Expand the folder and you can see the "cucumber" folder-> bin--> cucumber.js this file helps you to execute cucumber tests.
 
 

Installing Gherkin Plugin

 
 As you all know cucumber uses "Gherkin" language, Where it is written in simple plain English language with certain sets of keywords like "Given, When,Then". We have installed the cucumber package in the above example, that is specific to the above project. After installing the package we need to install the Gherkin plugin, To write the cucumber scripts.
 
 
 

Creating first feature file

 
As you know cucumber works on Gherkin, we need to create .feature file first. So first create a folder with name "feature" and inside the feature folder create "stepdefinition" folder. Create a "Login.feature" file inside the "feature" folder.
 
First, let's take the simple example of a user login. You need to enter the below code in the .feature file.
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Scenario: In order to login to the angular app  
  7.         Given user navigates to the angular app website  
  8.         When user enters the Vaid username and password  
  9.         Then user should be successfully loggedin to the application  
 
In order to run this in "Visual Studio code," you need to navigate to "node-module" -> bin-> cucumber.js file this will help you to run the cucumber files.
 
You need to enter the below command inside the terminal.
  1. .\node_modules\.bin\cucumber-js features  
Suppose you want to execute the particular feature, then you can enter the command, as shown below:
  1. .\node_modules\.bin\cucumber-js .\features\Login.feature  
 
Now let's create a step definition file for the "login.feature" file. 
  1. var {Given, When, Then} = require('cucumber');  
  2.   
  3. Given('user navigates to the angular app website', function () {  
  4.     // Write code here that turns the phrase above into concrete actions  
  5.     return console.log('Given - user navigates to the angular app website');  
  6.   });  
  7.   
  8.   When('user enters the Vaid username and password', function () {  
  9.     return console.log('When - user enters the Vaid username and password');  
  10.   });  
  11.   
  12.   Then('user should be successfully loggedin to the application', function () {  
  13.     return console.log('Then - user should be successfully loggedin to the application');  
  14.   });  
After entering the above code, run the feature file like mentioned above. When you run this, all the steps gets executed. The above example is just to know how to the feature file is created and executed.
 

Adding Multiple Scenarios to the feature file

 
When you are adding multiple scenarios to the feature file, you should be careful about the repeating scenarios. Let us say for ex: you have two scenarios, one is for login with valid user and one with an invalid user, as mentioned below.
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Scenario: In order to login to the angular app  
  7.         Given user navigates to the angular app website  
  8.         When user enters the Vaid username and password  
  9.         Then user should be successfully loggedin to the application  
  10.   
  11.     Scenario: In order to login to the angular app with invalid login  
  12.         Given user navigates to the angular app website  
  13.         When user enters the InVaid username and password  
  14.         Then user should not be successfully loggedin to the application  
In such cases, the step definition is the same for both, but there are some changes, i.e w.r.t user name, and password we are entering. So in such cases, we can use a regular expression to avoid duplicate step definition and in the feature file, as mentioned below.
 
Every regular expression should start with ^/ and ends with $/ and the dynamic values should be like "([^"]*)", for every dynamic value in feature file should be represented with double quotes.
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Scenario: In order to login to the angular app  
  7.         Given user navigates to the angular app website  
  8.         When user enters the "Valid" username "valid" password  
  9.         Then user should "be" successfully loggedin to the application  
  10.   
  11.     Scenario: In order to login to the angular app with invalid login  
  12.         Given user navigates to the angular app website  
  13.         When user enters the "InValid" username "InValid" password  
  14.         Then user should "not" successfully loggedin to the application  
  1. var {Given, When, Then} = require('cucumber');  
  2.   
  3. Given(/^user navigates to the angular app website$/, function () {  
  4.     // Write code here that turns the phrase above into concrete actions  
  5.     return console.log('Given - user navigates to the angular app website');  
  6.   });  
  7.   
  8.   When(/^user enters the "([^"]*)" username "([^"]*)" password$/, function (username, password) {  
  9.     return console.log("When - user enters the "+ username+" username "+password+" password");  
  10.   });  
  11.   
  12.   Then(/^user should "([^"]*)" successfully loggedin to the application$/, function (loginType) {  
  13.     return console.log("Then - user should "+ loginType+" successfully loggedin to the application");  
  14.   });  

Adding Background

 
In the above example, we have seen multiple scenarios. But there are some repeating line for the above two scenarios in feature file. i.e Given statement, Navigating to the URL is the same for both the scenario. So you can mention it in the "Background". Any repeated statement that is same for both the scenarios can be mentioned in "Background".
 
Let's see this with example: In the below example, I have removed the "Given" statement from both the scenarios and i have placed that statement in "Background" which you need to declare after the "Feature". If you execute the cucumber test, it should work as same and there is no change in the step definition.  
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Background:  
  7.         Given user navigates to the angular app website  
  8.   
  9.     Scenario: In order to login to the angular app  
  10.         When user enters the "Valid" username "valid" password  
  11.         Then user should "be" successfully loggedin to the application  
  12.   
  13.     Scenario: In order to login to the angular app with invalid login  
  14.         When user enters the "InValid" username "InValid" password  
  15.         Then user should "not" successfully loggedin to the application  
 
As you can see in the above result. The "Given" statement has been executed twice, since there are two scenarios.
 

Parameterizing the Scenarios 

 
In the above scenarios, we created 2 scenarios for Valid and Invalid user. Each time, we cannot create the scenario to execute different sets of test data and it is not valid to create so many scenarios for the same execution. In order to avoid this we need to use "Scenario Outline" it allows to execute scenario with different sets of data. We can modify the scenario in the above example like this: 
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Background:  
  7.         Given user navigates to the angular app website  
  8.   
  9.     Scenario Outline: In order to login to the angular app  
  10.         When user enters the Valid "<username>" valid "<password>"  
  11.         Then user should "<loginStatus>" successfully loggedin to the application  
  12.   
  13.   
  14.         Examples:  
  15.             | username  | password | loginStatus |  
  16.             | Testuser1 | pass123  | passed      |  
  17.             | Testuser2 | pass222  | failed      |  
  18.             | Testuser3 | pass333  | passed      |  
In the above example, under "examples" you can pass the different sets of test data and you can also see we have only once scenario, to run this different sets of data.
 
Below is the execution result with different sets of data.  
 
 
You can also add Multiple Feature file and Step definition files to your project. The code looks the same as above. 
 

Working with DataTables and Multiple feature files

 
Let us look at some example. For this, I have created one more feature file in which you need to select the country of the user to login. 
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Background:  
  7.         Given user navigates to the angular app website  
  8.   
  9.     Scenario Outline: In order to login to the angular app  
  10.         When user enters the Valid "username" valid "password"  
  11.         Then Select the user country  
  12.         |Country | Zipcodes|  
  13.         | India | 1000  |  
  14.         | Japan | 1001  |  
  15.         | South Korea   | 1002  |  
  16.         Then user should "loginStatus" successfully loggedin to the application  
For the country, I have given some country Name and Zipcodes. You need to read this data table in your Step definition. This data is only for that particular step and "Examples" is for entire scenario wherever it is used.
 
Your Step definition looks like this:
  1. var {Given, When, Then} = require('cucumber');  
  2.   
  3. Then(/^Select the user country$/, function (table) {  
  4.     // Write code here that turns the phrase above into concrete actions  
  5.   
  6.     var data = table.hashes()[1]; // this is an array type so arr[1] is nothing but Japan in the feature file  
  7.     return console.log("the user country is: "+ data["Country"] + " Zipcode is: "+ data["Zipcodes"]);  
  8.   });  
 
You can see in the result, IT has executed previous feature files as well. This is the example for Multiple feature file and you can see the country and the zip code in the last scenario i.e "Japan" and Zipcode is "1001" is printed.
 

Cucumber Tags

 
Tags are like grouping of the scenarios, With the tagname, you can execute the testcases. Suppose in the one feature film you have more than 10 scenarios, but at the time of execute you may want to run only certain scenarios. Then you can mention the scenarios with a tag name.
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Background:  
  7.         Given user navigates to the angular app website  
  8.   
  9.     @prod  
  10.     Scenario Outline: In order to login to the angular app  
  11.         When user enters the Valid "username" valid "password"  
  12.         Then Select the user country  
  13.         |Country | Zipcodes|  
  14.         | India | 1000  |  
  15.         | Japan | 1001  |  
  16.         | South Korea   | 1002  |  
  17.         Then user should "loginStatus" successfully loggedin to the application  
When you want to execute above feature file with tag Name "@prod"
  1. .\node_modules\.bin\cucumber-js --tags '@prod'  
Only the tagname with prod gets executed.
 
 

Cucumber Hooks

 
At a times you need some annotations where you can initialize the database connection, Close the database connection or you need to open the URL before starting any tests. In order to execute it you have something call hooks. "BeforeAll, AfterAll, Before, After"
 
Let's look at some examples here:
  1. var {Given, When, Then, BeforeAll, AfterAll, Before, After} = require('cucumber');  
  2.   
  3. BeforeAll(function(){  
  4.     //You can initialize any data base connection  
  5.     console.log("Inside Before All method");  
  6. });  
  7.   
  8. AfterAll(function(){  
  9.     //close of database connection  
  10.     console.log("Inside After All method");  
  11. });  
  12.   
  13. Before(function(){  
  14.     //Manage to open the url and wait for certain timeout  
  15.     console.log("Inside Before method");  
  16. });  
  17.   
  18. After(function(){  
  19.     //close the browser  
  20.     console.log("inside after method");  
  21. });  
  22.   
  23. Given(/^user navigates to the angular app website$/, function () {  
  24.     // Write code here that turns the phrase above into concrete actions  
  25.     return console.log('Given - user navigates to the angular app website');  
  26.   });  
  27.   
  28.   When(/^user enters the Valid "([^"]*)" valid "([^"]*)"$/, function (username, password) {  
  29.     return console.log("When - user enters the "+ username+" username "+password+" password");  
  30.   });  
  31.   
  32.   Then(/^user should "([^"]*)" successfully loggedin to the application$/, function (loginType) {  
  33.     return console.log("Then - user should "+ loginType+" successfully loggedin to the application");  
  34.   });  
 

Cucumber Tag Hook 

 
You can create hook based on Tag, below is the example. I have given the same tag name that I had mentioned in the feature file.
  1. var {Given, When, Then, BeforeAll, AfterAll, Before, After} = require('cucumber');  
  2.   
  3. BeforeAll(function(){  
  4.     //You can initialize any data base connection  
  5.     console.log("Inside Before All method");  
  6. });  
  7.   
  8. AfterAll(function(){  
  9.     //close of database connection  
  10.     console.log("Inside After All method");  
  11. });  
  12.   
  13. Before("@prod",function(){  
  14.     //Manage to open the url and wait for certain timeout  
  15.     console.log("Inside Before method");  
  16. });  
  17.   
  18. After("@prod",function(){  
  19.     //close the browser  
  20.     console.log("inside after method");  
  21. });  
  22.   
  23. Given(/^user navigates to the angular app website$/, function () {  
  24.     // Write code here that turns the phrase above into concrete actions  
  25.     return console.log('Given - user navigates to the angular app website');  
  26.   });  
  27.   
  28.   When(/^user enters the Valid "([^"]*)" valid "([^"]*)"$/, function (username, password) {  
  29.     return console.log("When - user enters the "+ username+" username "+password+" password");  
  30.   });  
  31.   
  32.   Then(/^user should "([^"]*)" successfully loggedin to the application$/, function (loginType) {  
  33.     return console.log("Then - user should "+ loginType+" successfully loggedin to the application");  
  34.   });  

Generating HTML reports

 
This is the last section of this article. So far, we have learned all the basics of cucumber, like creating a file, creating a feature file, and adding the step definition, creating tags, and creating hooks. Essentially all the things we executed in the Visual Studio editor terminal itself. Now let us see how to generate HTML reports and view an output.
 
First you need to download "cucumber-html-reporter" from npm website (https://www.npmjs.com/package/cucumber-html-reporter)
 
Just execute this command in our VisualStudio code editor terminal
 
npm install cucumber-html-reporter --save-dev 
 
Once it is executed, you can recheck in "package.json." It will be added like this:
  1. {  
  2.   "name""cucumberjsbasics",  
  3.   "version""1.0.0",  
  4.   "description""",  
  5.   "main""index.js",  
  6.   "scripts": {  
  7.     "test""echo \"Error: no test specified\" && exit 1"  
  8.   },  
  9.   "author""Mahalasa",  
  10.   "license""ISC",  
  11.   "dependencies": {  
  12.     "cucumber""^7.0.0-rc.0"  
  13.   },  
  14.   "devDependencies": {  
  15.     "cucumber-html-reporter""^5.2.0"  
  16.   }  
  17. }   
We need to create "cucumber_report.json " as mentioned in npm website. To create the .json file. Execute the below command.
  1. .\node_modules\.bin\cucumber-js --format=json:cucumber_report.json  
If you see in the left pane, the "cucumber_reporter.json" file will be generated
 
 
Once the cucumber_report.json file is generated, you need to create "index.js" file and add the below code:
  1. var reporter = require('cucumber-html-reporter');  
  2.    
  3. var options = {  
  4.         theme: 'bootstrap',  
  5.         jsonFile: './cucumber_report.json',  
  6.         output: './cucumber_report.html',  
  7.         reportSuiteAsScenarios: true,  
  8.         scenarioTimestamp: true,  
  9.         launchReport: true,  
  10.         metadata: {  
  11.             "App Version":"0.3.2",  
  12.             "Test Environment""STAGING",  
  13.             "Browser""Chrome  54.0.2840.98",  
  14.             "Platform""Windows 10",  
  15.             "Parallel""Scenarios",  
  16.             "Executed""Remote"  
  17.         }  
  18.     };  
  19.    
  20.     reporter.generate(options);  
  21.       
Now you need to execute the below command. Since the output is already generated and placed in .json file, you just need to run index.js file.
  1. node index.js  
 
 
 So far, we executed the command separately, one by one. Now let us see we can execute this report commands through the "package.json" file.
 
For this, you need to update your package.json file, as shown below.
 
I have added "cuke", and then i have added the two commands mentioned above in a single line. 
  1. {  
  2.   "name""cucumberjsbasics",  
  3.   "version""1.0.0",  
  4.   "description""",  
  5.   "main""index.js",  
  6.   "scripts": {  
  7.     "test""echo \"Error: no test specified\" && exit 1",  
  8.     "cuke"".\\node_modules\\.bin\\cucumber-js --format=json:cucumber_report.json && node index.js"  
  9.   },  
  10.   "author""Mahalasa",  
  11.   "license""ISC",  
  12.   "dependencies": {  
  13.     "cucumber""^7.0.0-rc.0"  
  14.   },  
  15.   "devDependencies": {  
  16.     "cucumber-html-reporter""^5.2.0"  
  17.   }  
  18. }  
Now you need to execute the below command:
  1. npm run cuke  
You can see that the same reports have been generated. This is how we generate reports in cucumber. There are many ways to generate a report. I just showed one popular report example.
 
I think that I have covered all the basics of cucumber using VScode editor.
 
In the next article, I will be covering: How to integrate protractor configuration with Cucumber
 
Thank you, and Happy Coding! :-)