How To Use Annotations In Cucumber Framework
By Mohit Joshi, Community Contributor - December 19, 2024
The world of testing has a lot of frameworks that have accelerated the development cycle, one of which is the Cucumber Framework. It can be easily understood even by someone who does not have the technical expertise.
Cucumber is a testing framework that supports Behavior Driven Development (BDD). This technique can be well understood by all the contributors to the project, such as QA, Business Analysts, etc. Cucumber’s source was originally written in the Ruby language and was later extended to Java.
Cucumber users annotation to define or describe an action. It is a predefined text that helps the compiler understand and execute the command accordingly. This guide explains how to use annotations in Cucumber.
- Setting up for Cucumber Testing
- What are Cucumber Annotations
- How to use Cucumber Tags
- What are Hooks in Cucumber
- How to use Cucumber Hooks
- When to Use Cucumber Hooks
- What are the different types of Cucumber Hooks?
- How to Run Hooks
- How to Use the ‘Background’ Keyword
Setting up for Cucumber Testing
Let’s first set up the project using the Cucumber framework.
- Step 1: Install IDE and Set up Java
You can install any IDE, however, for the sake of this tutorial, let us use Eclipse IDE. Also, install the latest version of Java on your system. To ensure that Java is installed on your system, run a quick command in the terminal to check the Java version.
Java -version
- Step 2: Create a new Maven Project
To create a Maven project, you must install the Maven Plugin, however, in the latest versions of Eclipse, it comes installed already.
- Step 3: Add Maven Dependencies to your project
In this step, you have to add several dependencies to your project. Navigate to the pom.xml file in the folder structure and then add the following dependencies – Cucumber Java, Cucumber JUnit, JUnit, and Selenium Java. You can get these dependencies from Maven Repository.
- Step 4: Create a feature file
Navigate to src/test/resources in the folder structure and then create a feature folder. Also, add a feature file in the feature folder there.
- Step 5: Install the Cucumber Plugin
You can easily install the Cucumber plugin from the Eclipse marketplace. The Cucumber plugin lets the codebase know that you’re creating a Cucumber project.
- Step 6: Create Step Definitions
To create Step definitions, navigate to the src/test/java package and then add a step definition folder and file there.
- Step 7: Create a Runner Class
Create a class file in the Step Definitions folder and add the runner class script. The runner class will look something like this.
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
@RunWith(Cucumber.class)
@CucumberOptions(features=”src/test/resources/Features”,
glue={“StepDefinitions”})
public class TestRunner {
}
What are Cucumber Annotations
Annotations in Cucumber are predefined texts that contain some meaning for the compiler for the execution. In this section, let us dive a little deeper and understand hooks, tags, and more.
How to use Cucumber Tags
Tags are used to associate a test with a particular scenario.
For instance, there are multiple feature files containing several scenarios. However, if you require to test only a few scenarios out of all the scenarios from all the feature files, the brute force way combines all the required scenarios in one feature file and then executes it from the test runner class. However, this method becomes a headache and does not bring flexibility. Therefore, tags in such cases come in handy, separating multiple scenarios and executing the required ones only.
Tags are the names that you give to the scenarios in the feature file. To assign a name, you have to use the ‘@’ symbol before writing the name. For example, to assign a scenario smoke test, use @smoke in the feature file right above the scenario you want to name.
@name_of_the_test
Scenario: Define the scenario
Let’s take a practical example to understand how to use cucumber tags.
- Create a Feature File
@Smoke
Feature: Feature to demo tags
Scenario: Example 1
Given
When
And
- Create Step Definitions
Here, let us create a sample step definition file, where you will bind the necessary code with the scenarios in the feature file.
- Create a Test Runner Class
In the below test, the scenario is marked with @SmokeTest, therefore, in the test runner class file, you will assign those tag names that you want to run.
@RunWith(Cucumber.class)
@CucumberOptions(
features=”src/test/resources/Features”,
glue= {“StepDefinition”},
tags = {“@SmokeTest”}
)
public class TestRunner {
}
- If you have created multiple scenarios, then the above test runner class file will allow the execution of only that code only that matches the names you have provided inside the ‘tags’ script.
- To execute several scenarios, you must use ‘OR’ keyword while writing the names of the scenarios you want to use inside the ‘tags’ script. For example, to execute all the scenarios that are marked with either @Smoke or @Regression, add tags = {“@Smoke OR @Regression”}.
- Similarly, the ‘AND’ keyword is used when you have to execute scenarios that contain both keywords. For example, in tags = {“@Smoke AND @Regression”} it will execute scenarios that contain both names.
- Use the ‘NOT’ keyword to ignore the scenarios that you want to skip from getting executed.
What are Hooks in Cucumber
Hooks in Cucumber are special blocks of code that run before or after each scenario. They allow you to manage setup and teardown actions or control specific parts of your test execution.
The primary purpose of implementing hooks is to reduce code duplication by setting up particular scripts as reusable code blocks. A hook can be defined anywhere throughout the project; however, it is placed in a separate folder for better organization and maintainability.
How to use Cucumber Hooks
Consider a situation where you are creating multiple scenarios, however, while writing the scenarios you notice that before or after the execution of each scenario some sets of actions are the same. Therefore to prevent the repeated use of the same code, hooks are used. Hooks are the blocks of code that run before or after each scenario.
Also Read: Cross Browser Testing Using Cucumber
To define hooks, you must use annotations like @Before and @After. There are three types of hooks in Cucumber – Scenario, Step, and Conditional. Scenario Hooks run before and after each scenario. Step Hooks run before and after each step. Conditional Hooks are linked with tags for conditional execution.
The idea behind implementing hooks is to manage the setup & teardown and allow better maintenance of code.
- Create a Feature File
@RegressionTest Feature: Feature to Hooks Scenario: Example 2 Given When Then
- Create Step Definitions
Create the necessary step definitions file required for your project.
- Create a Class for Hooks
Create a Java class for hooks. Note that, you must create this hooks class file inside the Step Definitions package.
package StepDefinitions; import io.cucumber.java.After; import io.cucumber.java.Before; public class Hooks { @Before // write code here which you want to be executed before each scenario } @After // write code here which you want to be executed after each scenario }
- Create a Test Runner Class
package cucumberOptions; import org.junit.runner.RunWith; import io.cucumber.junit.Cucumber; import io.cucumber.junit.CucumberOptions; @RunWith(Cucumber.class) @CucumberOptions(features="src/test/java/Features", glue="StepDefinitions", tags="@RegressionTest") public class TestRunner { }
When to Use Cucumber Hooks
Cucumber Hooks are essential to manage the lifecycle of the testing project effectively. However, to further level up the efficiency one must be aware of when to use Cucumber Hooks to create maintainable and useful tests.
- For Setup: A Before hook is used to prepare the test environment, including launching a browser, initializing database connections, and much more.
- For Tear Down: An After hook can be used to clean up after the test, such as closing the browser, clearing cookies, and much more.
- Wrap up a scenario: An Around Hook can be used to wrap an entire scenario with custom logic, such as to enable or disable features for specific tests.
- Creating Reports: Hooks are also used for creating reports or logging details about a failed test. This is useful for debugging purposes.
What are the different types of Cucumber Hooks?
In a test execution lifecycle, there are several instances where one is required to use hooks to reduce code duplication, enhance maintainability, and write an efficient test script.
Cucumber provides several types of hooks, and here are different types of cucumber hooks.
1. Before Hook
The Before hook is executed before each test scenario. Therefore, it is generally used to initialize the test scenario and configure resources needed for the test, such as launching the browser before each scenario, setting up database connections, calling APIs, and more.
const { Before } = require('@cucumber/cucumber'); Before(function () { console.log("Setting up the environment before the scenario"); });
2. After Hook
The After hook is executed after each test scenario; therefore, it is generally used to reset the environment to its previous state. It is also used in cleanup tasks such as closing the browser instance, deleting test data, and more.
const { After } = require('@cucumber/cucumber'); After(function () { console.log("Cleaning up the environment after the scenario"); });
3. BeforeStep Hook
The BeforeStep hook is executed before each individual step, therefore, it is generally used for step-level initialization or logging.
const { BeforeStep } = require('@cucumber/cucumber'); BeforeStep(function () { console.log("Before executing the step"); });
4. AfterStep Hook
The AfterStep hook is executed after each individual step. Therefore, it is generally used for capturing screenshots and cleaning up temporary data.
const { AfterStep } = require('@cucumber/cucumber'); AfterStep(function () { console.log("After executing the step"); });
5. Tagged Hooks
These hooks are useful for executing specific hooks only on scenarios equipped with particular tags. They are useful for applying custom logic to certain scenarios without affecting others.
const { Before, After } = require('@cucumber/cucumber'); // Run this hook before scenarios tagged with @smoke Before({ tags: "@smoke" }, function () { console.log("Setup for smoke tests"); });
6. Around Hook
It is a useful Cucumber hook in wrapping around a scenario to run a specific code both before and after the scenario’s execution. It handles full control by running any conditional code around a single test scenario.
const { Around } = require('@cucumber/cucumber'); Around(function (runScenario) { console.log("Starting the scenario"); runScenario(); console.log("Ending the scenario"); });
Also Read: Page Object Model in Cucumber
How to Run Hooks
In the test lifecycle, Hooks are executed automatically without any requirement for additional commands. Cucumber automatically detects them and runs them at specified points. Here’s how to set up hooks and run Hooks in Cucumber.
- Define hooks in a separate file for better code maintenance.
- Import Hooks in the test file. The cucumber automatically detects Hooks if placed in the same directory as the test file.
- Execute the test suite using the following command.
mvn test
How to Use the ‘Background’ Keyword
Tags and Hooks gives an overview of Cucumber Annotations. Now, let’s look at one more important keyword which helps in improving the overall maintainability of our code. Background keyword is a group of steps that are common to all the scenarios in a feature. It is defined once and for all in the project. It improves the readability and reusability of the code and prevents repeating steps in every scenario.
Moreover, It is pretty similar to hooks however, the background is visible in the feature file.
Now, let’s understand how to use the ‘background’ keyword with the help of an example.
- Create a Feature File
Feature: Test bstackdemo
Scenario: Check ‘Add to Cart’ button
Given user is logged in
When user clicks on ‘Add to Cart’ button
Then product is displayed in the cart
Scenario: Check ‘Favorite’ button is working
Given user is logged in
When user clicks on ‘Favorite’ button
Then product is displayed in the ‘Favorites’ page
In the above feature file, it can be clearly seen that the same Given step is used for two scenarios. Therefore, let us create a common step with the help of the ‘background’ keyword. The new feature file will look like this.
Feature: Test bstackdemo
Background:
Given user is logged in
Scenario: Check ‘Add to Cart’ button
When user clicks on ‘Add to Cart’ button
Then product is displayed in the cart
Scenario: Check ‘Favorite’ button is working
When user clicks on ‘Favorite’ button
Then product is displayed in the ‘Favorites’ page
After this, create the necessary Test Runner class and Step Definitions for the feature file and you’re good to go running a successful test using the ‘background’ keyword.
Cucumber is an amazing testing framework that supports BDD (Behavior Driven Development). It offers several tools that ease our testing experience. Cucumber supports several programming languages allowing users to be more flexible.
You can use Cucumber with popular automation frameworks like Selenium and Cypress. Testing on a real device cloud gives you the advantage of identifying all the issues faster and in a more seamless manner. BrowserStack offers a real device cloud platform that allows you to run your tests on a combination of 3500+ devices, browsers, and operating systems.
What is the difference between Background and Hooks in Cucumber?
Background and hooks are robust mechanisms in Cucumber that let execute shared or pre-defined logic in different scenarios. Having said that, they serve different purposes and are leveraged in different contexts. Here are the main differences between Background and Hooks in Cucumber.
Background | Hooks |
---|---|
Background keyword is a group of steps that are common to all the scenarios in a feature. It is defined once and for all in the project. It improves the readability and reusability of the code and prevents repeating steps in every scenario. | Hooks allow you to manage setup and teardown actions or control specific parts of your test execution. |
Background focuses on defining the steps that come across during execution. | Hooks focuses on the execution of the code. |
The Background is strictly limited to gherkin setups and doesn’t work with non-gherkin setups. | Hooks can manage complex setups such as calling APIs, handling complex databases, and much more. Therefore, Hooks are more flexible than Background. |
Conclusion
In software testing, Hooks play an essential role in managing the setup and tear-down logic. Moreover, it is also useful in executing conditional logic for specific scripts without affecting the other elements of the test. Their ability to go along with the tags allows them to execute scripts for selective applications, which is a versatile feature in automation testing.
You can use Cucumber with popular automation frameworks like Selenium and Cypress. Testing on a real device cloud gives you the advantage of identifying all the issues faster and in a more seamless manner.
BrowserStack offers a real device cloud platform that allows you to run your tests on a combination of 3500+ devices, browsers, and operating systems.
Useful Resources
- Cucumber Best Practices to follow for efficient BDD Testing
- Cypress Cucumber Preprocessor: Uses & Configuration
- What is Cucumber Framework? (Benefits of Cucumber Testing)
- End to End (E2E) Testing in Cucumber
- Test Automation using Selenium and Cucumber Framework: Tutorial
- How to Run Tests with Cypress and Cucumber: Tutorial
- Cross Browser Testing Using Cucumber
- How to take Screenshot of Failed Test Cases in Cucumber
- Page Object Model in Cucumber
- Playwright and Cucumber Automation
- Selenium vs Cucumber: Core Differences
- TestNG vs Cucumber: Core Differences