Top 5 Cucumber Best Practices For Selenium Automation

Top 5 Cucumber Best Practices For Selenium Automation

Do you know Cucumber is a great tool used to run acceptance tests using the plain-text functional descriptions with Gherkin? Behavior Driven Development strategy or BDD, as it is popularly known, is implemented using the Cucumber tool.

The best part about using the Cucumber BDD framework are:

  • Tests are first documented before being implemented.
  • Tests are easy to understand for a user who doesn’t even know the functionality.
  • It efficiently combines the automated tests having a living documentation and specifications that can be executed.

Can’t wait to get started with Cucumber? To help you out, we will be diving into some of the best Cucumber practices that will enable you to write better scenarios using the Gherkin language. You will also get a clearer picture of the Behavior Driven Development concepts with these practices.

Basics Of Cucumber BDD Framework

Before we jump dive into Cucumber best practices, there are a few things you need to understand about the Cucumber BDD framework. To work with Cucumber, you would need three types of files as described below:

  • Feature File – It servers as an entry point to the Cucumber tests. It is the file where your test scenarios are written in Gherkin language. A Feature file may contain single or multiple test scenarios. The Feature file is used as a live document and ends with .feature extension.
  • Step Definition – It contains the piece of code, in your chosen programming language, with some annotations attached to it. On seeing a Gherkin Step, Cucumber executes the code which is contained within the Step. The annotation has a pattern that links the Step Definition to the matching steps defined in the Feature File.
  • Others – We may need other files to execute tests at different levels. For example, we are testing the Web UI; then, we will be using a tool like Selenium, which might use a framework of its own like the Page Object Model. Since in this post, our primary focus is Cucumber best practices, let us leave the other files’ detailing for some other time.

In the next section of this blog, we will understand feature files in detail and how we can use them efficiently. These are some of the essential practices you should implement for successfully using Cucumber & Selenium. As already stated, we will use Gherkin to write the scenarios in the Cucumber BDD framework. Let us now understand in detail some Cucumber best practices.

1. Creating A Feature File

We will start by creating a file in our project structure that will consist of the steps to mimic a certain functionality. Since in this post, we will understand Cucumber best practices, we will only focus on how we can write our features file to model our test scenarios. We will see the practical implementation later. As an example, let us take the Login functionality using Gherkin.

Use Case: Model the behavior of logging into an application with valid credentials-

  1. Create a file with .feature extension inside the project folder. For example, let us name it “ Login.feature ”.
  2. Inside the file, we will give a title depicting the functionality. So in our example it can be something like “ Feature: Login Action ”.
  3. We will now start writing our scenarios in the feature file. The general syntax for writing a scenario in a feature file is-
 As [a user]
 I want to [perform some action]
 for [ achieving a result]

So using the above two points let us start with writing a Feature-

Feature: Login Action

Scenario: As an existing user, I want to login successfully.

With this you need to make a note of the important points listed below-

  • It is advised that you make your feature file independent from other functionalities. This means try to make each feature specific to a single functionality.
  • You can make your feature file understandable by using the same language as the requirement is specified, i.e., always try to describe the actions as they would have been done by the client.

Next, in the feature file, you will be writing the Scenarios. Scenarios are simply the behavior of a functionality. While testing, we might have to write multiple scenarios to cover the test scope. To write a scenario, we use Keywords defined by Gherkin. The primary keywords used in Gherkin sentences are –

  1. Given – Defines the pre-condition of the test.
  2. When – Defines the user action that will be performed.
  3. Then – Defines post-condition or the outcome of the test.
  4. But – Used to add negative conditions to the test.
  5. And – Used to add condition(s) to the test.

Note that you only need to state what you want to do in the feature file and not how you want to do it. The how part will be taken care of in the Step Definition file, which we will see later in this article.

See below an example of a poorly written scenario-

Scenario: As an existing user, I want to login successfully
Given the user is on the Home page
When the user navigates to the Login page
And the user can see the login form
And the user enters username and password
And the user is able to click on the Submit button 
Then the user is logged in successfully
And the successful login message is displayed

There is no point in writing such lengthy scenarios with unwanted details as it makes it difficult to read and maintain. A better way to write the same scenario with fewer lines is as follows-

Scenario: As an existing user, I want to login successfully.
Given the user is on the Home page
When the user navigates to the Login page
And the user enters username and password
Then the successful login message is displayed

Did you see how with fewer sentences, we can depict the same scenario by including only the necessary details and ignore beating around the bush? 🙂

Below are a few points that you need to keep in mind while writing scenarios in Gherkin-

  • Always remember that the order of your statements must follow Given-When-Then. Since ‘Given’ implies a pre-condition , ‘When’ refers to an action and ‘Then’ refers to a post condition for the action, it will be unclear to write ‘Then’ before ‘When’.
  • Always remember that Given-Then-When should occur only once per scenario. You can extend any sentence by using ‘And’. This is because every scenario depicts an individual functionality. If we will include multiple Then-When, there would be no point of being a single functionality.
  • Make sure that your sentences are consistent when talking about perspective. This means if the scenario description is described in first person, then the sentences should also be in first person to maintain homogeneity.
  • Try to write minimum steps in a scenario. It helps in making the scenario understandable and clear.
  • Try writing brief sentences which are explanatory.
  • Try to make your scenarios independent. If the scenarios are interlinked, it may generate errors, for instance, in case of parallel test execution.

2. Separating Feature Files

When testing with live applications, you might have to create multiple feature files. It becomes crucial to bifurcate the feature in different files. You can organize files so that all the features related to a specific functionality are grouped in a package or a directory. This is another one of the essential Cucumber best practices we recommend for seamless BDD implementation.

For example, consider an e-commerce application – you can organize the file such that, at the first level, you can have a package, say Orders, and in that, you can have multiple features like Pending Orders, Completed Orders, Wishlist, etc. Doing so will make your project organized, and it will be easy for you to locate the tests as per the functionality.

3. Using The Correct Perspective

At times it becomes very confusing as to what perspective should you write your scenarios in – first person or third person? The official Cucumber BDD framework documentation uses both the point of view. Below are the arguments for both the point of views-

First Person

BDD was created by Dan North, who, in his article “Introducing BDD,” recommends the use of the first person. Using the first person is rational since it depicts keeping yourself in place of the person actually performing the action.

Third Person

The people who prefer the third-person point of view state that using first-person can confuse the reader. It does not clarify who is performing the action, i.e., an individual user, an admin, or some user with a particular set of roles. It is argued that third person usage shows the information formally and minimizes the risk of making any false assumptions about who is actually involved in performing/testing a scenario.

So, all in all, there is no mandate on using any one point of view; the one practice that you have to remember is to maintain consistency. The description should resonate with the test steps and be from a single perspective.

4. Additional Keywords Used In Gherkin

Apart from the commonly used keywords discussed above, there are a few more that are used in Gherkin. If you want to implement the Cucumber best practices, this is an important one to start practicing.

Background

Background simplifies adding the same steps to multiple scenarios in a given feature. This means, if some common steps have to be executed for all the scenarios in a feature, you can write them under the Background keyword.

For example, to order a product from an e-commerce website, you will have to do the following steps-

  1. Open the website
  2. Click on the Login link
  3. Enter the username and password
  4. Click on the Submit button

Once you have completed the above steps, you can search the product, add that product to your cart, and proceed with the checkout and payment. Since the above steps would be common for many functionalities in a feature, we can include them in the Background.

Feature:  Add To Cart

Background:
Given the user is on the Home page
And the user navigates to the Login page
And the user enters username and password
Then the successful login message is displayed

Always try to keep the background as short as possible since it will be difficult to understand the following scenario if it is kept lengthy. The key with the Cucumber Feature file is, the shorter, the better.

Scenario Outline

A Scenario outline is similar to the test data corresponding to a test scenario. It is no compulsion to write a scenario with a scenario outline, but you can write it if needed.

Scenario outline: Order with different quantities

Given: User searches for HP Pen Drive
When: Add the first result on the page with quantity <qty>
Then: Cart should display <qty> pen drive

Examples:

|qty|
|1|
|5|
|24|

Doc Strings

If the information in a scenario does not fit in a single line, you can use DocString. It follows a step and is enclosed within three double-quotes. Though often overlooked, it is one of the most crucial Cucumber best practices to follow.

Scenario: Login with a valid-user
Given the user is on the Home page
And the user navigates to the Login page
And the user enters username and password
Then the successful login message is displayed with text:

“You have successfully logged into your account! There are multiple discount offers 
waiting for you!!”

Data Table

The Data Table is quite similar to Scenario Outline. The main difference between the two is that the Scenario outline injects the data at the scenario level, while the data table is used to inject data at the step level.

  • Data tables serve to input data at a single step.
  • It is not necessary to define the head of a data table, but it is advised to maintain a reference to data for easy understanding.
Scenario: Login with a valid-user
Given the user is on the Home page
And the user navigates to the Login page
And the user enters <username> and <password>

| username | password |
| test1 | password1 |

As shown in the example above, you can use a data table at single steps with different data that you may need to inject.

Languages

Cucumber is not limited to writing the scenarios in English. Similar to the conventions followed in English, you can write the scenarios in multiple human languages. The official Cucumber documentation has all the information about using the Language feature and the dialect code of various languages.

For example, to use French as the language to write your scenarios, you can use the # language as a header in the functionality like below-

# language : fr

( Note: fr is the dialect code for French)

Tags

There may be cases when you need not execute all the scenarios of the test. In such cases, you can group specific scenarios and execute them independently by using Tags. Tags are simply the annotations used to group scenarios and features. They are marked with @ followed by some notable text.

Examples-

@SmokeTest @RegressionTest
Scenario: ….

@End2End
Feature: ….

Note that the tags are inherited in the feature file by all the components, viz the scenario outline, scenario, etc. Similarly, if there is a tag on the Scenario Outline, the data examples will also inherit the tag.

The above examples can be configured for execution as shown below-

tags={“@End2End”} All the scenarios of the feature under @End2End tag would be executed.
tags={“@SmokeTest”} All the scenarios under @SmokeTest would be executed.
tags={“@SmokeTest , @RegressionTest”} This type of definition denotes OR condition hence, all the scenarios that are under @SmokeTest tag or @RegressionTest tag would be executed.
tags={“@SmokeTest” , “@RegressionTest”} In such definition, all the scenarios under the @SmokeTest AND @RegressionTest will be executed.
tags={~“@End2End”} All the scenarios under @End2End tag will be ignored.
tags={“@SmokeTest , ~@RegressionTest”} All the scenarios under @SmokeTest tag will be executed but the scenarios under @RegressionTest tag would be ignored.

Similar to the examples above, you can make combinations of tags as per your requirement and execute the scenarios/features selectively.

5. Step Definition(Step Implementation)

So far, we have only understood what our scenarios would do as part of Cucumber best practices. But the next and vital step to automate using Cucumber Selenium is adding Step Definition that would do the how part, i.e., how would the scenario execute. When Cucumber runs a step in the Scenario, it refers to a matching Step Definition for execution.
Implementation of steps can be done in Ruby, C++, Javascript, or any other language, but we will use Java for our example.

If you are using an IDE that already has Gherkin and Cucumber installed, you will see suggestions to create a new .java file or select one which has the steps implemented already. On selecting any of the options, a method will be created in the class. For instance, we are resting the step definition for below step-

Given the user is on Home Page

A method would be generated automatically, with annotation having the header text same as that of the step description:

@Given(“^the user is on Home Page$”)
public void homePage() throws Throwable{

//Java code to check the above description
….
…..
}

To create step implementation of scenarios that get data from Scenario Outline or Data Tables, the data is included in the annotations as regular expressions, along with passing as a parameter to the method.

@When(“^Add the first result on the page with quantity \”([0-9]+)”\$”)
public void addQuantity(int qty) throws Throwable{

//Java code to pass qty in the qty field
…
...

}

And that is how you can implement the steps that you write in the Feature file using Gherkin. Always remember the below points while implementing step definitions-

  • Try to create reusable step definitions.
  • Reusable step definitions will make your tests maintainable, and in case of any change in the future, you will have to make minimum changes to your framework.
  • You can use Parameterization in scenario outlines to reuse step definitions.

Wrapping Up

You are now familiar with some of the most important Cucumber best practices to follow with your BDD strategy or while implementing Cucumber & Selenium. To summarize this blog post, we would recommend you to-

  • Try to write scenarios in the feature file in a way the user would describe them. This would help you create crisp and concise steps.
  • Avoid coupled steps, i.e., always prefer creating one action per step. This would save you from unnecessary errors.
  • Reuse step definitions as much as possible to improve code maintainability.
  • Try to leverage the use of Background to minimize unnecessary addition of the same steps in different scenarios.

Happy testing!