In this blog, I’m going to share with you how to create executable Jar File for automation framework designed with Cucumber, Java, Selenium and Maven.
What is the executable jar file?
The executable jar file to execute Cucumber Scenarios includes all build structures files of the framework along with packages, and dependencies. That works as an execution of the test cases.
Why so we need a jar file?
We have a framework that contains numerous test cases.Instead of giving you the code, we’ll give you a tool that can run these tests and make reports customized for different needs like quick checks and in-depth checks. Sometimes, the client doesn’t want to see or understand how the framework works. They simply want the final reports like Allure, HTML, or PDF reports which help them assess the quality of the product. The client doesn’t require an IDE like IntelliJ or Eclipse, for instance. They just need a user interface where they can click a button to generate the reports. This approach helps reduce their complexity. In such scenarios, we need a JAR file. This JAR file facilitates the triggering of test cases according to specific Cucumber tags and generates the necessary reports.
Technology used for this project (Executable jar file)
In the software testing world, the commonly used tool is selenium. Most of the creators used this stable and compatible tool for Automation.
- Selenium: The software testing community has had faith in Selenium since 2004, as it’s been a reliable tool for testing. Most of us are familiar with selenium. If you are a beginner, please check out here.
- Maven: The maven is a build management tool. Maven builds and manages Java-based projects. Maven provides an easy way to share the JARs across several projects. If you want to know more about Maven please check out here
- Java: We are using the programming language Java for this project.
- Cucumber: Cucumber supports behavior-driven development as a tool.
Prerequisites for the project (Executable jar file)
The following tools might have been installed on your system to executable jar file.
- Java: Please check, is jdk installed on your system? If you cannot find the Java version on your system, please check out here to install Java.
- Maven: Please check, is maven installed on your system? If you could not find the maven version on your system, please check out here to install maven.
- Cucumber: When you create the maven project, you need to add cucumber plugins in the project setting window. If you wish to explore the cucumber in detail, here is the link Link you can refer to.
Framework Overview of Bdd Cucumber project
I am assuming you know the basic Bdd cucumber project architecture. For the creation of a jar, we need to modify the folder structure. Here I am highlighting the required files and key factors.
Let’s see the framework folder structure.
When we created the new project for the executable jar file, we could see the simple folder structure provided by Maven.
- SRC Folder: The SRC folder is the parent folder of a project that will include the main and test folders. For the QA environment, normally we are using the test folder. The main folder is used for the development environment. The created jar contains all files inside the src folder.
- Test Folder: Inside the test folder, Java and resources folders are available.
- Java Folder: This folder contains the Java classes where the actual code is present.
- Resources Folder: The Resources folder contains the resources file, test data file, and document files.
- Pom.xml: In this file, we are managing the dependencies and plugins that are required for automation.
Structure of the Test Folder
The test folder design is the base of the executable jar file creation for the cucumber framework. Inside the java folder, we have to create a directory (org.BDD). In this directory, we need to create a subdirectory on the basis of code design Let’s see the subdirectory
1. Core
The core folder contains a subfolder. In the core folder, we set the standard code like…
- Hooks: This Java class contains the basic before and after functions. These functions are set for the browser initialization and termination. Also, we can set the before and after methods, steps, and scenarios as per project requirements.
package org.CBDD.core;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import org.CBDD.utilities.WebUtil;
public class Hooks extends TestContext {
@Before
public void beforeScenario(Scenario scenario) {
driver = WebUtil.initWebDriver();
}
@After
public void afterScenario() {
WebUtil.tearDown();
}
}
- Main: While executing Java programs, by default, the JDK calls the Main functions. For the execution of a jar, we need the java command, hence we need to define the main class in our framework.
package org.CBDD.core;
public class Main {
public static void main(String[] args) throws Throwable {
String[] arguments = {};
io.cucumber.core.cli.Main.run(arguments);
}
}
- TestContext: The TestContext Java class is used to define instances of classes and declare global variables. Here, Java classes extend the TestContext class and inherit the properties and values of the content.
package org.CBDD.core;
import org.openqa.selenium.WebDriver;
import org.CBDD.pages.CalculatorPage;
public class TestContext {
public static WebDriver driver;
public static CalculatorPage calculatorPage;
}
- TestRunner: The Java class contains the @CucumberOptions properties. In the TestRunner class, we define the glue between the step definitions and feature files. In the case of BDD, this TestRunner class plays an important role.
package org.CBDD.core;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
import org.testng.annotations.DataProvider;
@CucumberOptions(features = "classpath:Features",
glue = {"org.CBDD"})
public class TestRunner extends AbstractTestNGCucumberTests {
@DataProvider
@Override
public Object[][] scenarios() {
return super.scenarios();
}
}
2. Steps:
The Steps folder contains the Java classes for step definitions. In this folder, we need to specify the path in the glue option of the @CucumberOptions annotation so that the feature files can detect the step definitions during execution. If the glue is not properly mentioned, an ‘undefined step’ error will occur.
Inside the Steps folder, each Java class contains the implementations of the steps as defined in the feature files.
package org.CBDD.steps;
import org.CBDD.core.TestContext;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.testng.Assert;
import org.CBDD.pages.CalculatorPage;
import java.io.IOException;
public class CalculatorSteps extends TestContext {
public CalculatorSteps() {
calculatorPage = new CalculatorPage();
}
@Given("I am on Calculator page")
public void iAmOnCalculatorPage() throws IOException {
calculatorPage.iAmOnCalculatorPage();
}
@When("I enter number {int}")
public void iEnterNumber(int number) {
calculatorPage.iEnterNumber(number);
}
@And("I click on operator {string}")
public void iClickOnOperator(String operator) {
calculatorPage.iClickOnOperator(operator);
}
@Then("I verify the result as {int}")
public void iVerifyTheResultAs(int expectedResult) {
String actualResult = calculatorPage.iVerifyTheResultAs();
Assert.assertEquals(actualResult, String.valueOf(expectedResult));
}
}
3. Pages:
The Pages folder contains the page classes that house the actual code. The page functions are called in the step class.
package org.CBDD.pages;
import org.CBDD.core.TestContext;
import org.openqa.selenium.By;
import org.CBDD.utilities.ConfigUtil;
import java.io.IOException;
public class CalculatorPage extends TestContext {
public void iAmOnCalculatorPage() throws IOException {
driver.get(ConfigUtil.getPropertyValue("base_url"));
}
public void iEnterNumber(int number) {
driver.findElement(By.xpath("//span[@onclick='r(" + number + ")']")).click();
}
public void iClickOnOperator(String operator) {
driver.findElement(By.xpath("//span[@onclick=\"r('" + operator + "')\"]")).click();
}
public String iVerifyTheResultAs() {
driver.findElement(By.xpath("//span[@onclick=\"r('=')\"]")).click();
return driver.findElement(By.xpath("//div[@id='sciOutPut']")).getText().trim();
}
}
4. Utilities:
The Utilities folder contains utilities to reduce the repetition of code. It includes the WebUtil class, which contains functions for browser initialization and termination.
package org.CBDD.utilities;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.CBDD.core.TestContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebUtil extends TestContext {
public static WebDriver initWebDriver() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
return driver;
}
public static void tearDown() {
driver.quit();
}
}
5. Resources:
Normally, this folder is used to store resources such as test data, properties, and configuration files. In this case, we need to declare the feature files inside the resources folder because the created target folder contains a non-editable feature folder. This setup ensures that feature files are correctly packaged and accessible during the build process.
- Features: Features contain the feature files. We need to provide the path of this folder in glue. Here we provide the path “classpath:Features” beecause, the jar does not contain the absolute path.
@cucumberOptions(features = “classpath:Features”, glue = {“org.CSDD”})
In the feature file, we use the Gherkin language to write test cases.
Feature: Verify Calculator Operations
@addsub
Scenario Outline: Verify addition and subtraction of two numbers
Given I am on Calculator page
When I enter number <number>
And I click on operator '<operator>'
And I enter number <number1>
Then I verify the result as <expectedResult>
Examples:
| number | operator | number1 | expectedResult |
| 5 | + | 2 | 7 |
| 9 | - | 3 | 6 |
@muldiv
Scenario Outline: Verify multiplication and division of two numbers
Given I am on Calculator page
When I enter number <number>
And I click on operator '<operator>'
And I enter number <number1>
Then I verify the result as <expectedResult>
Examples:
| number | operator | number1 | expectedResult |
| 6 | * | 4 | 24 |
| 2 | / | 2 | 1 |
- Cucumber.properties: This properties file is used to set the Cucumber configuration. Normally during the execution, this file is detected by Cucumber automatically and the configuration is implemented. The same configuration can be set in the TestRunner class. In the case of CI/CD execution or jar execution, the priority goes to the cucumber.properties file rather than the TestRunner class. Hence, we need to implement the same configuration in both the TestRunner class and the cucumber.properties file.
cucumber.publish.enabled:true
CUCUMBER_PUBLISH_TOKEN:0b5c7164-ab9e-43ed-b6ba-da66c5e07c02
cucumber.features= Features
cucumber.glue=org.CBDD.core,org.CBDD.steps
- Manifest file: This file is the most important file for executing the jar file. The manifest file by default houses the META-INF folder. This file contains information about the files packaged in a JAR file. This manifest file specifies the Main class and the jar packages that are available in the External Libraries folder. The purpose of having a manifest file is to specify the main class, which is easily detected by the JAR during execution. Without a manifest file, the JAR cannot identify the main class; hence, the JDK is confused about selecting the execution entry point.
How to add Manifest file in project folder structure
For adding the manifest file to your project, there are two ways.
Add the manifest file from the project settings.
- Assuming you are using the IntelliJ IDEA editor, follow the procedure below:
- Click on the File menu and select Project Settings.
- Click on the file menu and select the project setting
- Select the artifacts from the project structure screen
- Click on ‘+’ icon, select the jar option -> form module with dependencies
- Select the main class -> select the checkbox of ‘copy to the output directory and link via manifest’ -> enter the directory for META-INF/MANIFEST.MF as ‘project directory + src\test\resources’
- Click on the Apply button and the OK button
- You can see the manifest file stored in your resources folder.
Add the manifest file with the org.apache.maven.plugins
Here, we need to add the Maven plugin to the pom.xml file. In this plugin, we need to mention the path where the manifest file is stored and the Main class package.
<build>
<plugins>
<plugins>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version> <!-- Use the latest available version -->
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>src/test/resources/</classpathPrefix>
<mainClass>org.CBDD.core.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugins>
</plugins>
</build>
6. POM.xml File
Maven has the pom.xml file that contains information about the project and configuration details. It contains the default architecture for most projects.
Project dependencies configuration is specified in the pom.xml file as per requirement. We have added the plugins provided by Maven as per our project needs and configuration.
Let’s see some required plugins for jar creation.
- Maven-jar-plugin: This plugin provides the capability to build the jar. It helps to create a jar for test classes of the project. In this plugin, we need to mention the manifest file path that will decide the main class of the jar file. We can check the latest version of this plugin on the Maven repository. In case, you are having a problem setting the plugin, you can go with the maven-jar-plugin dependencies.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifestFile>src/test/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
- Maven-dependency-plugin: When we create the jar, we will see it in the target folder. The jar file contains the manifest file and packages inside the jar directory or target folder. Hence, this plugin comes into the picture. The plugin copies all dependencies or packages from the pom.xml file and stores them in the jar directory folder (target folder). During execution, the jar requires these dependencies/packages/jars.
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
- Maven-resources-plugin: The resources folder contains the test data, properties, and document files. Without this plugin, when we create the jar, the jar doesn’t contain the files from the resources folder. In case we need to provide these files externally to the jar. So, to avoid this painful process, we can use this plugin. This plugin works by copying all files from the resource folder into the jar files. After the creation of the jar file, we can check the availability of this file in the command prompt with this command: “Jar tf file.jar”
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>copy-resource-one</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<resources>
<resource>
<directory>src/test/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
How to create the jar
As you have followed the above process and configuration, we can proceed with jar creation. We can create the jar in two ways.
- Create a jar with the help of the command: ‘mvn package’
In your project directory, open the terminal. Maven has a command to create a jar, which is ‘mvn package’. When you execute this command, it starts the process of creating the JAR and runs your test cases. After the completion of this process, you will find the jar file in the target folder.
- Create the jar file with maven lifecycle steps
In your IntelliJ IDEA, there is an E-Maven tab. This tab includes the Lifecycle sub-tab.
Follow this process:
Clicks on the lifecycle tab and follow below diagram.
Execution of jar file
Once you successfully create the JAR along with the dependencies in the target folder, you can use some commands related to the JAR file.
- Check the directories in jar file
To check the directories included in a jar file, you can use the command ‘jar tf filename.jar’. This command will list all the files and directories contained within the jar file.
Output:
- Run the jar file
Normally, when we run a jar file, the jar file starts with the main class. Whatever configurations the main class includes, those files will execute. The command to run a jar file is: Java jar jarFileName.jar
Output:
- Run the specific test case from jar
Normally, we execute the smoke or regression test cases. We differentiate the test cases by tag name. In this project, we have two scenarios with the tags “@addsub” and “@muldiv.”
Based on the tags, we can select the test cases for execution. Open the terminal and change the directory to the target folder. The command for execution is as follows: java -cp jarFileName.jar io.cucumber.core.Main featurefileName –tags “@tagname”
Example“
java -cp CalculatorBDD-1.0-SNAPSHOT-tests.jar io.cucumber.core.cli.Main Features/Calculator.feature –tags “@smoke”
java -cp CalculatorBDD-1.0-SNAPSHOT-tests.jar io.cucumber.core.cli.Main Features/Calculator.feature –tags “@regression”
Output:
Conclusion:
The creation of a jar file for a Cucumber Maven framework, as described, represents a strategic approach that offers flexibility in executing test cases directly from the jar file. This JAR file helps minimize issues related to redundant code and ensures stable and customized execution.
In conclusion, creating a jar with Selenium, Java, and BDD using Cucumber helps deliver high-quality software. By following best practices like designing a robust framework architecture, leveraging Maven plugins, and configuring the cucumber.properties file, we can generate an executable JAR file for effective automation testing.This enhances the stability of the test cases and reduces the failure rate.
Source Code:
Wish to take a look at the source code? You can attain a clearer and more straightforward understanding by visiting the repository at the following URL, where you’ll find a comprehensive guide that outlines the steps to follow.
https://github.com/spurqlabs/JAR-File-Creation-
Click here to read a more blogs to increase your software testing skills.
3An SDET with hands-on experience in the life science domain, including manual testing, functional testing, Jira, defect reporting, web application, and desktop
application testing. I also have extensive experience in web and desktop automation using Selenium, WebDriver, WinAppDriver, Playwright, Cypress, Java, JavaScript, Cucumber, maven, POM, Xray, and building frameworks.