Saturday 10 September 2022

How to run cucumber scenarios from executable jar ? | Selenium Java, TestNG, Cucumber, Maven | How to use io.cucumber.core.cli.Main.main() ?

 In this blog post , we will learn majorly the following topics. 

1. How to create an executable jar for cucumber+selenium+testng+maven project ?
2. How to run scenarios from generated jar ? 

To create an executable jar for maven project there are many jar plug-in's available in the maven space. 
In this example, I'd like to demonstrate it using maven-assembly-plugin. 

The demo project for HRM application can  be found at GitHub  or download this maven zip file

You could also watch this no voice video tutorial for quick references
(Pls do subscribe for more automation updates)

java -jar -Dcucumber.filter.tags="@HRMLogin" CucumberTestNGSeleniumExecutableJar-0.0.1-SNAPSHOT-jar-with-dependencies.jar 



Now, let's see the core part that we start with pom.xml
We need to have the maven-assembly-plugin is given the pom file, i.e., add below piece of code in the pom.xml file. 

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-assembly-plugin</artifactId>
	<version>3.1.1</version>
	<configuration>
		<archive>
			<manifest>
				<addClasspath>true</addClasspath>
				<mainClass>com.sadakar.common.BasePage</mainClass>
			</manifest>
			<manifestEntries>
				<Class-Path>.</Class-Path>
			</manifestEntries>
		</archive>
		<descriptorRefs>
			<descriptorRef>jar-with-dependencies</descriptorRef>
		</descriptorRefs>
	</configuration>
	<executions>
		<execution>
			<id>make-assembly</id>
			<phase>package</phase>
			<goals>
				<goal>single</goal>
			</goals>
		</execution>
	</executions>
</plugin>

In a java class, using "main" method, we need to pass the glue code, tags, plug-ins and etc that are related to cucumber as arguments. 
For example, I've used, BasePage.java class that should contain normal "main" method and  inside it use Main.main(....) to pass cucumber arguments so the scenarios based on tags would be runnable from command line. 
import package : import io.cucumber.core.cli.Main; in the BasePage.java class and the passing of arguments are shown in below class.  

BasePage.java
package com.sadakar.common;

import org.openqa.selenium.WebDriver;

import io.cucumber.core.cli.Main;

public class BasePage {

	public static WebDriver driver;
	public static void main(String args[]) throws Throwable {
	    try {
	        Main.main(new String[] { 
	    

	        "-g","com.sadakar.common",
	        "-g","com.sadakar.stepdefinitions",
	        "-g","com.sadakar.testng.runner",
	                    
	        "classpath:features", 
	        
	        "-t","@HRMLogin",
	        
	                
	        "-p", "pretty", 
	        "-p", "json:target/cucumber-reports/cucumber.json", 
	        "-p", "html:target/cucumber-reports/cucumberreport.html",
	        
	        "-m"
	    }
	    );
	} catch (Exception e) {
	        e.printStackTrace();
	        System.out.println("Main method exception : " + e);
	}
	}

}

In eclipse, build the project using below command: 

Ensure that any open folders, command prompts, chrome drivers in task manager are all closed.
Clean the project and then build it. 

clean package assembly:single -Dmaven.test.skip=true

Using -Dmaven.test.skip=true option we can skip the tests while the project builds! 


Click on the images to view them in gallery mode so the content provided is clear! 


This is how the log looks like when the build is in progress and is completed. 
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/softwares/Eclipse/eclipse-java-2021-09-R-win32-x86_64/eclipse/plugins/org.eclipse.m2e.maven.runtime.slf4j.simple_1.18.0.20210618-2246/jars/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [file:/D:/softwares/Eclipse/eclipse-java-2021-09-R-win32-x86_64/eclipse/configuration/org.eclipse.osgi/5/0/.cp/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/softwares/Eclipse/eclipse-java-2021-09-R-win32-x86_64/eclipse/plugins/org.eclipse.m2e.maven.runtime.slf4j.simple_1.18.0.20210618-2246/jars/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [file:/D:/softwares/Eclipse/eclipse-java-2021-09-R-win32-x86_64/eclipse/configuration/org.eclipse.osgi/5/0/.cp/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
[INFO] Scanning for projects...
[INFO] 
[INFO] --< CucumberTestNGSeleniumExecutableJar:CucumberTestNGSeleniumExecutableJar >--
[INFO] Building CucumberTestNGSeleniumExecutableJar 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Deleting C:\Users\sadakarp\eclipse-workspace\CucumberTestNGSeleniumExecutableJar\target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 5 source files to C:\Users\sadakarp\eclipse-workspace\CucumberTestNGSeleniumExecutableJar\target\classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Not copying test resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Not compiling test sources
[INFO] 
[INFO] --- maven-surefire-plugin:3.0.0-M7:test (default-test) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Tests are skipped.
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Building jar: C:\Users\sadakarp\eclipse-workspace\CucumberTestNGSeleniumExecutableJar\target\CucumberTestNGSeleniumExecutableJar-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-assembly-plugin:3.1.1:single (default-cli) @ CucumberTestNGSeleniumExecutableJar ---
[INFO] Building jar: C:\Users\sadakarp\eclipse-workspace\CucumberTestNGSeleniumExecutableJar\target\CucumberTestNGSeleniumExecutableJar-0.0.1-SNAPSHOT-jar-with-dependencies.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  26.979 s
[INFO] Finished at: 2022-09-10T20:21:45+05:30
[INFO] ------------------------------------------------------------------------

maven-assembly-plugin generates two jar files, they are

1. CucumberTestNGSeleniumExecutableJar-0.0.1-SNAPSHOT.jar
2. CucumberTestNGSeleniumExecutableJar-0.0.1-SNAPSHOT-jar-with-dependencies.jar


The jar with the dependencies is called fat jar file and this is the one we call as "executable" or "runnable" jar. 

Make sure that this jar contains the MANIFEST.MF file containing the class that has the main method. Use jar extract tools to view the content inside the jar, I've used "Java Decompiler". 

The MANIFEST.MF file should contain all the dependencies with Main-Class:com.sadakar.common.BasePage as shown in below. 

MANIFEST.MF
Manifest-Version: 1.0
Created-By: Apache Maven 3.8.1
Built-By: sadakarp
Build-Jdk: 16.0.2
Class-Path: cucumber-java-7.1.0.jar cucumber-core-7.1.0.jar cucumber-ghe
 rkin-7.1.0.jar cucumber-gherkin-messages-7.1.0.jar messages-17.1.1.jar 
 tag-expressions-4.1.0.jar cucumber-expressions-13.0.1.jar datatable-7.1
 .0.jar cucumber-plugin-7.1.0.jar docstring-7.1.0.jar html-formatter-17.
 0.0.jar create-meta-6.0.4.jar apiguardian-api-1.1.2.jar cucumber-testng
 -7.1.0.jar selenium-java-4.3.0.jar selenium-api-4.3.0.jar selenium-chro
 me-driver-4.3.0.jar auto-service-annotations-1.0.1.jar auto-service-1.0
 .1.jar auto-common-1.2.jar guava-31.1-jre.jar failureaccess-1.0.1.jar l
 istenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar jsr305-3.
 0.2.jar checker-qual-3.12.0.jar error_prone_annotations-2.11.0.jar j2ob
 jc-annotations-1.3.jar selenium-chromium-driver-4.3.0.jar selenium-json
 -4.3.0.jar selenium-devtools-v101-4.3.0.jar selenium-devtools-v102-4.3.
 0.jar selenium-devtools-v103-4.3.0.jar selenium-devtools-v85-4.3.0.jar 
 selenium-edge-driver-4.3.0.jar selenium-firefox-driver-4.3.0.jar seleni
 um-ie-driver-4.3.0.jar selenium-opera-driver-4.3.0.jar selenium-remote-
 driver-4.3.0.jar netty-buffer-4.1.78.Final.jar netty-codec-http-4.1.78.
 Final.jar netty-codec-4.1.78.Final.jar netty-handler-4.1.78.Final.jar n
 etty-common-4.1.78.Final.jar netty-transport-classes-epoll-4.1.78.Final
 .jar netty-transport-classes-kqueue-4.1.78.Final.jar netty-transport-na
 tive-epoll-4.1.78.Final.jar netty-transport-native-kqueue-4.1.78.Final.
 jar netty-transport-native-unix-common-4.1.78.Final.jar netty-transport
 -4.1.78.Final.jar netty-resolver-4.1.78.Final.jar opentelemetry-api-1.1
 5.0.jar opentelemetry-context-1.15.0.jar opentelemetry-exporter-logging
 -1.15.0.jar opentelemetry-sdk-metrics-1.15.0.jar opentelemetry-sdk-logs
 -1.15.0-alpha.jar opentelemetry-sdk-common-1.15.0.jar opentelemetry-sdk
 -extension-autoconfigure-spi-1.15.0.jar opentelemetry-sdk-extension-aut
 oconfigure-1.15.0-alpha.jar opentelemetry-sdk-trace-1.15.0.jar opentele
 metry-sdk-1.15.0.jar opentelemetry-semconv-1.15.0-alpha.jar jtoml-2.0.0
 .jar byte-buddy-1.12.10.jar commons-exec-1.3.jar async-http-client-2.12
 .3.jar async-http-client-netty-utils-2.12.3.jar netty-codec-socks-4.1.6
 0.Final.jar netty-handler-proxy-4.1.60.Final.jar netty-transport-native
 -epoll-4.1.60.Final-linux-x86_64.jar netty-transport-native-kqueue-4.1.
 60.Final-osx-x86_64.jar reactive-streams-1.0.3.jar netty-reactive-strea
 ms-2.0.4.jar slf4j-api-1.7.30.jar jakarta.activation-1.2.2.jar selenium
 -http-4.3.0.jar failsafe-3.2.4.jar selenium-safari-driver-4.3.0.jar sel
 enium-support-4.3.0.jar testng-7.1.0.jar jcommander-1.72.jar guice-4.1.
 0-no_aop.jar javax.inject-1.jar aopalliance-1.0.jar snakeyaml-1.21.jar 
 .
Main-Class: com.sadakar.common.BasePage

Now, let's run the jar file: 
Double click on the executable jar, it will start executing the scenarios! 

Or use below command to run the cucumber scenarios

Command is updated on 18 June 2023
java -jar -Dcucumber.filter.tags="@HRMLogin" CucumberTestNGSeleniumExecutableJar-0.0.1-SNAPSHOT-jar-with-dependencies.jar 



This execution, will generate, cucumber reports in "target" folder where the jar is located. 

The report is based on the plug-in(s) that we provide in BasePage.java file. 
For example, we gave it as 

"-p", "json:target/cucumber-reports/cucumber.json", 
"-p", "html:target/cucumber-reports/cucumberreport.html",


click on the "cucumberreport.html" file to analyze the report generated. 


That's all we have to do to create an executable cucumber, testng  jar file using maven and to run the scenarios from it. 

I hope you found this write-up useful, keep watch this blog site for more automation! 

No comments:

Post a Comment