Allure Report with karate 1.0.1 generating report with just one test case - maven

I am working on a maven project where I am creating both cucumber reports and allure reports with karate 1.0.1 via jenkins. But even though the detailed cucumber reports are getting generated, I am getting only one test case in the allure report
My TestParallelRunner.java file:
#CucumberOptions(plugin = {"pretty" , "html:target/cucumber-html-reports", "io.qameta.allure.cucumber4jvm.AllureCucumber5Jvm","json:target/cucumber/cucumber.json"})
//#KarateOptions(tags = "~#ignore")
public class TestParallelRunner {
#Test
public void testParallel() {
//String outputDir = "target//surefire-reports";
Builder testRun = new Builder();
testRun.path("classpath:com/api/automation/Features").outputCucumberJson(true).tags("~#ignore");
Results results = testRun.parallel(3);
generateReport(results.getReportDir());
Assertions.assertEquals(0, results.getFailCount(), "There are some Failed Scenarios");
}
public static void generateReport(String reportDirLocation) {
File reportDir=new File(reportDirLocation);
Collection<File> jsonFiles = FileUtils.listFiles(reportDir, new String[] {"json"}, true);
//jsonFiles.add(File("cucumber-report.json"));
List<String> jsonPaths = new ArrayList<>();
//jsonFiles.add("cucumber-report-2.json");
jsonFiles.forEach(file -> jsonPaths.add(file.getAbsolutePath()));
Configuration config = new Configuration(new File("target"), "Cucumber Report");
ReportBuilder reportBuilder = new ReportBuilder(jsonPaths, config);
reportBuilder.generateReports();
}
}
My pom.xml file:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version>
<maven.compiler.version>3.8.1</maven.compiler.version>
<maven.surefire.version>2.22.2</maven.surefire.version>
<karate.version>1.0.1</karate.version>
<allure.maven.version>2.11.2</allure.maven.version>
<allure-junit5.version>2.17.3</allure-junit5.version>
</properties>
<dependencies>
<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-junit5</artifactId>
<version>${karate.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/net.masterthought/cucumber-reporting -->
<dependency>
<groupId>net.masterthought</groupId>
<artifactId>cucumber-reporting</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-maven -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>${allure.maven.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-cucumber5-jvm -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-cucumber5-jvm</artifactId>
<version>2.17.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-junit5 -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-junit5</artifactId>
<version>${allure-junit5.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerArgument>-Werror</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.version}</version>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<testFailureIgnore>true</testFailureIgnore>
<systemProperties>
<property>
<name>allure.results.directory</name>
<value> ${project.build.directory}/allure-results</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
</project>
My Allure reports in my jenkins pipeline:
allure([
includeProperties: false,
jdk: '',
properties:[],
reportBuildPolicy:'ALWAYS',
results: [[path: '/allure-results']]
]
)
But my the json file created in my allure-results folder contains only the following entry:
{"uuid":"XXXXXXX-XXXXX-XXXXXX","historyId":"XXXXXXXXXXXXXXXXXX","testCaseId":"[engine:junit-jupiter]/[class:com.api.automation.TestParallelRunner]/[method:testParallel()]","testCaseName":"testParallel()","fullName":"com.api.automation.TestParallelRunner.testParallel","labels":[{"name":"junit.platform.uniqueid","value":"[engine:junit-jupiter]/[class:com.api.automation.TestParallelRunner]/[method:testParallel()]"},{"name":"host","value":"XXXXXX"},{"name":"thread","value":"XXXXXXX.main(1)"},{"name":"framework","value":"junit-platform"},{"name":"language","value":"java"},{"name":"package","value":"com.api.automation.TestParallelRunner"},{"name":"testClass","value":"com.api.automation.TestParallelRunner"},{"name":"testMethod","value":"testParallel"},{"name":"suite","value":"com.api.automation.TestParallelRunner"}],"links":[],"name":"testParallel()","status":"passed","stage":"finished","description":"","steps":[],"attachments":[],"parameters":[],"start":1652145767274,"stop":1652145775326}
Thus not getting a complete test execution picture the way cucumber report is showing :

A few points:
#CucumberOptions is not supported in Karate, read the docs: https://github.com/karatelabs/karate#parallel-execution
ensure that you tell Karate to emit the Cucumber JSON: https://github.com/karatelabs/karate/wiki/1.0-upgrade-guide#java-projects
for good measure use the latest version (1.2.0) as of now
Also refer: https://stackoverflow.com/a/54527955/143475

Related

Maven Surefire does not give correct test counts when executing Spock tests in parallel

My project contains a series of Groovy integration test scripts for a few APIs. Previously, these tests executed concurrently and took up to 3 hours to execute. I was able to reduce this time to just 5 minutes by using Spock's parallel execution feature.
The new problem is that the Maven Surefire reports no longer give the correct test counts for each test suite. The total test count is correct (more or less), but Surefire is mixing up which tests go in which report.
Here is my pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.dsg.payments</groupId>
<artifactId>e2e</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>This will be used to execute normal credit card End2End test cases</description>
<properties>
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-surefire-plugin.version>3.0.0-M3</maven-surefire-plugin.version>
<gmavenplus-plugin.version>1.11.0</gmavenplus-plugin.version>
<swagger-annotations-version>1.6.0</swagger-annotations-version>
<groovy.version>3.0.7</groovy.version>
<spock.version>2.0-M4-groovy-3.0</spock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>${spock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>0.15</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<testSourceDirectory>${project.basedir}/src/test/groovy</testSourceDirectory>
<resources>
<resource>
<directory>src/test/groovy</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/groovy</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
<!-- Groovy compiler -->
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>${gmavenplus-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>addTestSources</goal>
<goal>compileTests</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Java compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Unit Tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<includes>
<include>**/*.java</include>
</includes>
<skipTests>false</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
Here is an example of a test class
package com.dsg.payments.e2e.creditcard
import com.dsg.payments.paygate.ApiClient
import com.dsg.payments.paygate.api.AuthorizationApi
import com.dsg.payments.paygate.model.PaygateAuthorizationRequest
import com.dsg.payments.paygate.model.PaygateAuthorizationResponse
import com.dsg.payments.paygate.model.PaygateEncryptedCardTenderResult
import org.junit.Test
import org.springframework.http.HttpStatus
import org.springframework.web.client.HttpClientErrorException
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Title
import spock.lang.Unroll
import util.Constants
import util.CreditCardType
import util.EntityFactory
#Title("CreditCard-Authorization")
class Authorization extends Specification {
// Constants
#Shared
private static final applicationName = Constants.APPLICATION_NAME
#Shared
private static final referer = Constants.REFERER
#Shared
private static final basePath = Constants.BASE_PATH
#Shared
private AuthorizationApi authorizationApi
def setupSpec() {
// Setup ApiClient to make requests to stage AN01
ApiClient authApiClient = new ApiClient()
authApiClient.setBasePath(basePath)
authorizationApi = new AuthorizationApi(authApiClient)
}
#Test
#Unroll
def "Auth request with valid #cardType card returns authorized response"(CreditCardType cardType) {
when:
PaygateAuthorizationResponse authorizationResponse = authorizationApi.authorize(applicationName, EntityFactory.getPaygateAuthorizationRequest(cardType), referer)
PaygateEncryptedCardTenderResult tenderResult = authorizationResponse.getTenderResults().getEncryptedCardTenderResults().get(0)
then:
// No exception thrown by authorization api client means successful 201 response
authorizationResponse != null
where:
cardType << [
CreditCardType.VISA_Credit_1,
CreditCardType.VISA_Debit,
CreditCardType.VISA_Commercial_Debit,
CreditCardType.VISA_Commercial_Credit,
CreditCardType.VISA_Purchasing_Credit,
CreditCardType.VISA_3DS_Not_Enrolled,
CreditCardType.DISCOVER,
CreditCardType.AMERICANEXPRESS_1,
CreditCardType.MASTERCARD_Debit,
CreditCardType.MASTERCARD_Credit,
CreditCardType.MASTERCARD_Premium_Credit,
CreditCardType.DINERS,
CreditCardType.JAPANCREDITBUREAU
]
}
#Test
#Unroll
def "Auth request with valid cvv for #cardType returns cvv response M"(CreditCardType cardType) {
when:
PaygateAuthorizationResponse authorizationResponse = authorizationApi.authorize(applicationName, EntityFactory.getPaygateAuthorizationRequest(cardType), referer)
PaygateEncryptedCardTenderResult tenderResult = authorizationResponse.getTenderResults().getEncryptedCardTenderResults().get(0)
then:
// No exception thrown by authorization api client means successful 201 response
authorizationResponse != null
tenderResult.getCvvResponse() == "M" // Raw CVV result code for "match"
where:
cardType << [
CreditCardType.VISA_Credit_2,
CreditCardType.VISA_Debit,
CreditCardType.VISA_Commercial_Debit,
CreditCardType.VISA_Commercial_Credit,
CreditCardType.VISA_Purchasing_Credit,
CreditCardType.VISA_3DS_Not_Enrolled,
CreditCardType.DISCOVER,
CreditCardType.AMERICANEXPRESS_2,
CreditCardType.MASTERCARD_Debit,
CreditCardType.MASTERCARD_Credit,
CreditCardType.MASTERCARD_Premium_Credit,
CreditCardType.DINERS,
CreditCardType.JAPANCREDITBUREAU
]
}
// ...
}
There are 3 more test classes (Capture, Refund, and Cancel) with a similar structure that use the #Unroll annotation to re-run the same test with different credit card numbers.
Interestingly, when using Spock parallel execution, Surefire adds an extra test to the report for each test method - one for each credit card and an additional test for the method itself. This is not a huge problem in itself, but it is less than ideal. The real problem is that the Surefire report mixes the classes together (for example, Capture tests end up in the Refund, Cancel, or Authorization reports). This makes it hard to tell from the report which tests failed.
I'll also include my SpockConfig.groovy, which configures the parallel execution:
runner {
filterStackTrace false
optimizeRunOrder true
parallel {
enabled true
dynamic(4.0)
}
}
It has taken much trial and error to get the pom in a state where the tests are all executing correctly in parallel fashion. This is the only combination of dependencies, plugins, and versions that works so far. The only thing that is wrong are the Surefire reports. Any ideas what I am missing?
First: I notice the surefire version in the POM shown is 3.0.0-M3. The mvnrepository.com maven-surefire-plugin list shows the latest is 3.0.0-M5 and a lot of the changes in the newer versions appear to be report related.
Second: check the Maven output log to see if the maven-surefire-report-plugin is being used. If it's there, ensure it is using the same version of Surefire as was used to run the tests. You can do that by adding this to the POM:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
You may not be using Failsafe for integration tests yet, but it's a good idea to keep the Surefire family of plugins using the same version. So when I need to adjust Surefire version, I set them all in the hope of saving someone future troubleshooting pain.

Adding a JNI library to a spring boot (maven) jar

I'm using Google Or-Tools library over a Java-Spring-Boot app, Windows 10 OS and Intellij IDE.
To make it work over intellij I did the following:
Install Microsoft Visual C++ Redistributable for Visual Studio 2019 (required according to the installation instructions).
Downloaded and extracted the OR-Tools library for Java (included 2 jars and a 1 dll file).
In Intellij, I added those jars as module dependencies (under a folder called lib).
Added the lib library path to VM options in Intellij run configurations.
Loaded the library statically in my code:
static {System.loadLibrary("jniortools");}
Now I can run the project successfully form Intellij.
Next I would like to pack everything to a spring boot jar that can run over any windows machine.
My folders structure is:
My pom file is pretty basic, a few dependencies with a standard spring-boot-maven-plugin:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
As I'm trying to pack the code using mvn install I'm getting package com.google.ortools.sat does not exist.
How can I make sure maven packs those 3rd party jars to the executable spring-boot jar?
UPDATE
I added to my pom file:
<dependency>
<groupId>com.google.ortools</groupId>
<artifactId>ortools</artifactId>
<version>LATEST</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/lib/com.google.ortools.jar</systemPath>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>LATEST</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/lib/protobuf.jar</systemPath>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>generate-test-sources</phase>
<configuration>
<tasks>
<mkdir dir="${project.basedir}/target/lib"/>
<echo message="Creating lib folder..."/>
<copy todir="${project.basedir}/target/lib">
<fileset dir="${project.basedir}/lib">
<include name="**/**"/>
</fileset>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
In addition adding to library path:
static {
try {
String orToolsDllLibrary = System.getProperty("user.dir") + "\\lib";
addLibraryPath(orToolsDllLibrary);
System.loadLibrary("jniortools");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addLibraryPath(String pathToAdd) throws Exception {
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[]) usrPathsField.get(null);
//check if the path to add is already present
for (String path : paths) {
if (path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length - 1] = pathToAdd;
usrPathsField.set(null, newPaths);
}
And now when running command java -jar myApp-0.0.1-SNAPSHOT.jar getting an exception:
Caused by: java.lang.NoClassDefFoundError: com/google/ortools/sat/CpSolver
at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na]
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3167) ~[na:na]
at java.base/java.lang.Class.getDeclaredMethods(Class.java:2310) ~[na:na]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463) ~[spring-core-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
... 29 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.google.ortools.sat.CpSolver
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588) ~[na:na]
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:129) ~[solver-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
... 33 common frames omitted
I am not sure how you added the library to your project? You don't seem to have done it through Maven, did you?
In the past I took the approach of adding it via using system scope in Maven (see here. This would give you something like this in your pom:
<dependency>
<groupId>com.google.ortools</groupId>
<artifactId>ortools</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/resources/lib/com.google.ortools.jar</systemPath>
</dependency>
However, this approach can also be a pain especially if you have to work multi-platform. Recently, I found this repo and that made my life much easier dealing with OR-tools. Hope this helps.
UPDATE:
I strongly recommend using the updated method below as it is much less of a headache:
<repositories>
...
<repository>
<id>bintray</id>
<url>https://dl.bintray.com/magneticflux/maven</url>
</repository>
....
</repositories>
<dependencies>
<dependency>
<groupId>com.skaggsm.ortools</groupId>
<artifactId>ortools-natives-all</artifactId>
<version>7.7.7810</version>
</dependency>
<!-- OR-tools needs protobuf -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.12.2</version>
</dependency>
</dependencies>
Then you can do a static load of the library:
static {
OrToolsHelper.loadLibrary()
}
Make sure to work with JDK >= 11 as elaborated here.
I tried:
First add the jniortools library to java.library.path pragmatically:
static {
String orToolsDllLibrary = System.getProperty("user.dir") + "\\lib";
addLibraryPath(orToolsDllLibrary);
System.loadLibrary("jniortools");
}
public static void addLibraryPath(String pathToAdd) throws Exception {
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[]) usrPathsField.get(null);
//check if the path to add is already present
for (String path : paths) {
if (path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length - 1] = pathToAdd;
usrPathsField.set(null, newPaths);
}
In pom file:
<dependencies>
....
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.12.2</version>
</dependency>
<dependency>
<groupId>com.google</groupId>
<artifactId>ortools</artifactId>
<version>0.0.2</version>
</dependency>
....
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>install-external</id>
<phase>process-resources</phase>
<configuration>
<file>${basedir}/lib/com.google.ortools.jar</file>
<repositoryLayout>default</repositoryLayout>
<groupId>com.google</groupId>
<artifactId>ortools</artifactId>
<version>0.0.2</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir="${project.basedir}/target/lib"/>
<echo message="Creating lib folder..."/>
<copy todir="${project.basedir}/target/lib">
<fileset dir="${project.basedir}/lib">
<include name="**/**"/>
</fileset>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

How to execute cucumber features parallely?

I have below feature files (Separate feature files) in src/test/resources/feature/ and I would like to run them in parallel. Like: One feature file has to execute in chrome and another one has to execute in another chrome instance as mentioned #Tags name.
#Regression
Scenario: Searching for HelpMate on Company Hompe page
Given I navigate to application URL
Then I verified title "Company - Production - Sign In" on Login Page
after
launched the URL
When I type username as "defined in config" in username filed on Login
page
And I type password as "defined in config" in password filed on Login
page
And I click Login button on Login page
And I wait for 15 seconds
Then I verified title "Company - Production - My Applications" on
Login Page
#Regression
Scenario Outline: Searching for different options on Company Home
page
Given I navigate to application URL
Then I verified title "Company - Production - Sign In" on Login Page
after launched the URL
When I type username as "defined in config" in username filed on Login
page
And I type password as "defined in config" in password filed on Login
page
And I click Login button on Login page
And I wait for 15 seconds
I'm using cucumber-java 1.2.5 version, and AbstractTestNGCucumberTests as runner. I'm able to run a single feature file but when i try to run 2 feature files using cucumber-jvm-parallel-plugin v#4.0.0 and maven surefire plugin v#2.40, it is not initialing the test class
(Error:cucumber.runtime.CucumberException: cucumber.runtime.CucumberException: Failed to instantiate class com.cvs.stepdefinition.LoginPage)
This error is gone after I used updated cucumber dependencies
cucumber-jvm-parallel-plugin-- Not using anymore as it is not required with latest version of cucumber libraries
<plugin>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>4.0.0</version>
<executions>
<execution>
<id>generateRunners</id>
<phase>validate</phase>
<goals>
<goal>generateRunners</goal>
</goals>
<configuration>
<glue>
<pakage>com.cvs.stepdefinition</pakage>
</glue>
<featuresDirectory>src/test/resources/features
</featuresDirectory>
<cucumberOutputDir>${project.build.directory}/
cucumberparallel</cucumberOutputDir>
<format>json,html</format>
<testFailureIgnore>true</testFailureIgnore>
<tags>
<tag>#Regression</tag>
</tags>
</configuration>
</execution>
</executions>
</plugin>
maven-surefire-plugin--UPDATED
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
TestNG.xml--UPDATED
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Testng Cucumber Suite" parallel="tests"configfailurepolicy="continue" thread-count="2">
<test name="SmokeSuite">
<parameter name="browserName" value="chrome"/>
<classes>
<class name="com.cvs.runner.TestSuiteRunner"></class>
</classes>
</test>
</suite>
I have tried overriding the method from AbstractTestNGCucumberTests and set the parallel attribute in #DataProvider annotation to true but still getting the same error.
#DataProvider(parallel=true)
public Object[][] features() {
return testNGCucumberRunner.provideFeatures();
}
POM.XML
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>testNewBDD</groupId>
<artifactId>TestAutomation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>TestAutomation</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<mainClass>ReportGenerator</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java8 -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java8</artifactId>
<version>4.2.6</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>4.2.6</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>4.2.6</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>3.6.0</version>
</dependency>
</dependencies>
</project>
Runner
#CucumberOptions(
strict = true,
monochrome = true,
features = {"src/test/resources/features"},
tags={"#Regression"},
glue = {"stepDef", "utils"},
plugin = {"pretty", "html:target/cucumber-html-report","json:target/cucumber-html-report/TestHomePage.json"},
//junit ={ "--step-notifications"},
dryRun = false
)
public class UITest {
private TestNGCucumberRunner testNGCucumberRunner;
#BeforeClass(alwaysRun = true)
public void setUpClass() throws Exception {
testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
}
#Test(groups = "cucumber", description = "Runs Cucumber Feature", dataProvider = "scenarios")
public void scenario(PickleEventWrapper pickleEvent, CucumberFeatureWrapper cucumberFeature) throws Throwable {
testNGCucumberRunner.runScenario(pickleEvent.getPickleEvent());
}
#DataProvider(parallel=true)
public Object[][] scenarios() {
return testNGCucumberRunner.provideScenarios();
}
#AfterClass(alwaysRun = true)
public void tearDownClass() throws Exception {
testNGCucumberRunner.finish();
}
}
There is only one feature file having 2 scenarios and i want these 2 scenarios to run on two different browser parallely. Please help me to resolve this.
Key Point : We would request you to use Cucumber-JVM v4.x.x specially to implement parallel execution without using cucumber-jvm-parallel-plugin as you are using pretty old dependency(v1.2.5) of Cucumber.
Note : In below implementation, we would be reading browser parameter from TestNG.xml file
First - Update POM.xml with correct set of io.cucumber dependencies as per any cucumber v >= 4.0.0 lets pick v4.2.6
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>4.2.6</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>4.2.6</version>
</dependency>
Second - Customize TestNGRunner class as per your framework need
package com.jacksparrow.automation.suite.runner;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import com.jacksparrow.automation.steps_definitions.functional.BaseSteps;
import cucumber.api.CucumberOptions;
import cucumber.api.testng.AbstractTestNGCucumberTests;
#CucumberOptions(features = "classpath:features/functional/",
glue = {"com.jacksparrow.automation.steps_definitions.functional" },
plugin = { "pretty","json:target/cucumber-json/cucumber.json",
"junit:target/cucumber-reports/Cucumber.xml", "html:target/cucumber-reports"},
tags = { "#BAMS_Submitted_State_Guest_User" },
junit ={ "--step-notifications"},
strict = false,
dryRun = false,
monochrome = true)
public class RunCukeTest extends Hooks {
}
Third - Implement Hooks.java
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import cucumber.api.testng.AbstractTestNGCucumberTests;
public class Hooks extends AbstractTestNGCucumberTests {
#Parameters({ "browser" })
#BeforeTest
public void setUpScenario(String browser){
//BaseSteps.getInstance().getBrowserInstantiation(browser); your browser setup method
}
}
Fourth - Update TestNG.xml under /src/test/resources/ as per your TestNGRunner Class and framework need.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Testng Cucumber Suite" parallel="tests" thread-count="2">
<test name="SmokeTest">
<parameter name="browser" value="chrome" />
<classes>
<class name="com.cvs.runner.TestSuiteRunner" />
</classes>
</test>
</suite>
Fifth - You shall be all set to run automation suite using TestNG in any of the following ways
- Run TestNG.xml directly from IDE
- From CMD - mvn test -Dsurefire.suiteXmlFiles=src/test/resources/testng.xml
- From POM.xml - Using Surefire Plugin
<profiles>
<profile>
<id>selenium-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Did you try to add number of treads in your .xml file, I do have it in mine.
So your .xml file will be:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Testng Cucumber Suite" parallel="tests" thread-count="2">
<test name="SmokeSuite">
<classes>
<class name="com.cvs.runner.TestSuiteRunner"></class>
</classes>
</test>
</suite>
(Also try to change parallel = "tests" to parallel methods. And if you r using priorities in your tests parallel running is not gonna work)
Cucumber 4 provides native support to run scenarios(not by features) in parallel.
you have to update your pom.xml dependencies to latest cucumber version.
cucumber-core 4.2.0, cucumber-java 4.2.0, cucumber-junit 4.2.0
In the runner file, you have add "--thread 2 " like a plugin. this will run the scenario in 2 threads.

Maven/ TestNg can't find allure #step annotation

Having a problem to implement allure #Step annotation into my maven project (tetsng, java).
(Updated) Sharing pom file:
eproject xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>src</groupId>
<artifactId>AutomationTestSuit</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.11.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src\main\resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<testResource>
<directory>src\test\resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<configuration>
<suiteXmlFiles>
<file>${project.basedir}/suites/smoke.xml</file>
</suiteXmlFiles>
<systemPropertyVariables>
<environment.properties>/environment.properties</environment.properties>
</systemPropertyVariables>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.1/aspectjweaver-1.9.1.jar"
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>e
I'm trying to add Step annotation to the page class but it gets the failure:
package com.pages.login_page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
public class LoginPageElements {
private WebDriver driver;
#FindBy(how = How.ID, using = "test")
private WebElement logonID;
#FindBy(how = How.ID, using = "test")
private WebElement logonPassword;
#FindBy(how = How.ID, using = "test")
private WebElement logonSubmit;
public LoginPageElements(WebDriver driver)
{
this.driver = driver;
PageFactory.initElements(driver,this);
}
#Step("login step") //step is underlined on this place with can't resolve symbol Step error
public void Login_as(String sUsername, String sPassword) {
logonID.sendKeys(sUsername);
logonPassword.sendKeys(sPassword);
logonSubmit.click();
}
#Step error example
the same problem I'm having with #Attachments while implementing it inside of MytestListener class:
see the screenshot
Please help me to figure out the problem.
I noticed that you are using out dated version of Allure. Here is correct import
<!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-testng -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.6.0</version>
</dependency>
With Allure 2 you do not need to configure Listener, but you need to configure AspectJ instead. Here you can find example for Maven + TestNG: https://docs.qameta.io/allure/#_testng
THE PROBLEM was with the idea community version. It appears that it doesn't support aspectj plugin. If someone will struggle with same issue please tale a look: https://www.jetbrains.com/help/idea/java-compiler.html
I my case the problem was in <scope>test</scope>.
I removed it from dependancy:
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>LAST_VERSION</version>
<scope>test</scope>
</dependency>
and #Step annotation starts to be recognized.

QueryDslPredicateExecutor Q-class is not generating

My Pom file is
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>4.0.6</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>4.0.6</version>
</dependency>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
After adding those dependency and plugin in pom.xml, I ran mvn clean install, QAutoManifest is not generating. I am new to jpa, Please help me.
public interface AutoManifestRepository extends CrudRepository<AutoManifest,String>,QueryDslPredicateExecutor<AutoManifest>{
}
And my Predicate class is
public class AutoManifestPredicate {
private AutoManifestPredicate() {
System.out.println("Predicate Object gets created");
}
static Predicate searchAutoManifest(SearchAutoManifest manifest) {
return null;
}
}

Resources