Hi ,
I'm unable to generate cucumber 7 extent report if I use TestNG, Cucumber hooks for different purposes(See code below for Hooks).
Ended up with the following error message on console:
FAILED CONFIGURATION: @BeforeClass setUpClass(org.testng.TestRunner@7d3430a7)
java.lang.IllegalArgumentException: The plugin specification 'com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:' has a problem:
Any help would be much appreciated. Reference example: https://github.com/grasshopper7/extentreports-cucumber7-adapter
pom.xml has the following dependencies
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>tech.grasshopper</groupId>
<artifactId>extentreports-cucumber7-adapter</artifactId>
<version>1.7.0</version>
<scope>test</scope>
</dependency>
Hooks.javaimport java.io.IOException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import com.sadakar.resource.utilities.Log;
import com.sadakar.resource.utilities.PropertyManager;
import io.cucumber.java.After;
import io.cucumber.java.AfterAll;
import io.cucumber.java.Before;
import io.cucumber.java.BeforeAll;
import io.cucumber.java.Scenario;
public class Hooks extends BasePage {
String chromeDriverPath = PropertyManager.getInstance().getChormeDriverPath();
String browserType = PropertyManager.getInstance().getbrowserType();
String ieDriverPath = PropertyManager.getInstance().getIEDriverPath();
@BeforeAll(order = 0) // Cucumber BeforeAll
public static void beforeAll() {
System.out.println("BeforeAll - This statement printed before all scenarios from Cucumber");
}
@Before(order = 0) // Cucumber Before Hook with order 0
public void before(Scenario scenario) throws IOException {
Log.info("Initiating the chrome driver from Cucumber Before hook with order=0");
System.setProperty("webdriver.chrome.driver", chromeDriverPath);
ChromeOptions options = new ChromeOptions();
// options.addArguments("--headless");
options.addArguments("--disable-gpu");
options.setPageLoadStrategy(PageLoadStrategy.NONE);
options.addArguments("--allow-insecure-localhost");
options.addArguments("--allow-running-insecure-content");
options.addArguments("--ignore-certificate-errors");
options.addArguments("--disable-web-security");
options.addArguments("--no-sandbox");
options.addArguments("--window-size=1280,1000");
options.setCapability("acceptSslCerts", true);
options.setCapability("acceptInsecureCerts", true);
driver = new ChromeDriver(options);
driver.manage().window().maximize();
}
@Before(order = 1) // Cucumber Before Hook with order 1
public void before2(Scenario scenario) {
Log.info("Scenario Name from Cucumber Before hook with order=2 --> " + scenario.getName());
Log.info("********************************************************************************");
}
@After(order = 0) // Cucumber After Hook with order 0
public void after(Scenario scenario) {
Log.info("Scenario Status from Cucumber After hook with order=0 --> " + scenario.getStatus());
Log.info("********************************************************************************");
}
@After(order=1)
public void quitDriver() {
Log.info("Quitting driver from Cucumber After hook with order=1");
driver.quit();
}
@After(order = 2) // Cucumber After Hook with order 1
public void takeScreenShotOnFailedScenario(Scenario scenario) {
Log.info("Taking screenshot from Cucumber After hook with order=2");
if ((scenario.isFailed())) {
final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
scenario.attach(screenshot, "image/png", scenario.getName());
}
}
@AfterAll(order = 0) // Cucumber BeforeAll
public static void afterAll() {
System.out.println("AfterAll - This statement printed after all scenarios from Cucumber");
}
}
DatabaseHooks.java
package com.sadakar.cucumber.common;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import com.sadakar.resource.utilities.Log;
public class DatabaseHooks {
// Connection object
private static Connection dbConn = null;
// Statement object
@SuppressWarnings("unused")
private static Statement stmt;
// Constant for Database URL
public static String DB_URL = "jdbc:sqlserver://11.123.3.12:1433;user=ua;password=password;database=testdatabase";
@BeforeSuite //TestNG annotation
public static Connection getDBConnection() {
try {
if (dbConn == null) {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dbConn = DriverManager.getConnection(DB_URL);
Log.info("Connected to Database - BeforeSuite TestNG");
}
else {
Log.info("Already Connected to Database - BeforeSuite TestNG");
}
} catch (Exception e) {
e.printStackTrace();
}
return dbConn;
}
@AfterSuite //TestNG
public static void closeConnection() {
if (dbConn != null)
try {
dbConn.close();
Log.info("Database connection closed - AfterSuite TestNG");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
extent.properties
extent.reporter.klov.start=false
extent.reporter.spark.start=true
extent.reporter.json.start=true
extent.reporter.pdf.start=true
extent.reporter.html.start=true
#extent.reporter.klov.config=src/test/resources/klov.properties
extent.reporter.spark.config=src/test/resources/spark-config.xml
#extent.reporter.html.config=src/test/resources/html-config.xml
extent.reporter.spark.out=test-output/Spark/ExtentSpark.html
extent.reporter.json.out=test-output/Json/ExtentJson.json
#extent.reporter.pdf.out=test-output/PdfReport/ExtentPdf.pdf
#extent.reporter.html.out=test-output/Html/ExtentHtml.html
#test,exception,category,device,author,log,dashboard - default order
extent.reporter.spark.vieworder=dashboard,test,category,exception,author,device,log
#embed image as base64 string src. Default is false
extent.reporter.spark.base64imagesrc=false
screenshot.dir=test-output/
screenshot.rel.path=../
systeminfo.os=Windows
systeminfo.version=8.1
#this is optional and creates the report in base folder name with date time format
basefolder.name=reports
basefolder.datetimepattern=d-MMM-YY HH-mm-ss
Eclipse console log:
[RemoteTestNG] detected TestNG version 7.0.1
log4j:WARN File option not set for appender [ERROR].
log4j:WARN Are you using FileAppender instead of ConsoleAppender?
log4j:WARN File option not set for appender [INFO].
log4j:WARN Are you using FileAppender instead of ConsoleAppender?
log4j:ERROR Could not find value for key log4j.appender.CONSOLE
log4j:ERROR Could not instantiate appender named "CONSOLE".
2022-08-04 00:45:47 INFO Log:40 - Connected to Database - BeforeSuite TestNG
log4j:ERROR No output stream or file set for the appender named [ERROR].
log4j:ERROR No output stream or file set for the appender named [INFO].
FAILED CONFIGURATION: @BeforeClass setUpClass(org.testng.TestRunner@7d3430a7)
java.lang.IllegalArgumentException: The plugin specification 'com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:' has a problem:
Could not load plugin class 'com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter'.
Plugin specifications should have the format of PLUGIN[:[PATH|[URI [OPTIONS]]]
Valid values for PLUGIN are: html, json, junit, message, pretty, progress, rerun, summary, teamcity, testng, timeline, unused, usage
PLUGIN can also be a fully qualified class name, allowing registration of 3rd party plugins. The 3rd party plugin must implement io.cucumber.plugin.Plugin
at io.cucumber.core.options.PluginOption.createCouldNotLoadClass(PluginOption.java:165)
at io.cucumber.core.options.PluginOption.parsePluginName(PluginOption.java:143)
at io.cucumber.core.options.PluginOption.parse(PluginOption.java:102)
at io.cucumber.core.options.RuntimeOptionsBuilder.addPluginName(RuntimeOptionsBuilder.java:66)
at io.cucumber.core.options.CucumberOptionsAnnotationParser.addPlugins(CucumberOptionsAnnotationParser.java:86)
at io.cucumber.core.options.CucumberOptionsAnnotationParser.parse(CucumberOptionsAnnotationParser.java:41)
at io.cucumber.testng.TestNGCucumberRunner.<init>(TestNGCucumberRunner.java:85)
at io.cucumber.testng.AbstractTestNGCucumberTests.setUpClass(AbstractTestNGCucumberTests.java:27)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:134)
at org.testng.internal.MethodInvocationHelper.invokeMethodConsideringTimeout(MethodInvocationHelper.java:63)
at org.testng.internal.ConfigInvoker.invokeConfigurationMethod(ConfigInvoker.java:348)
at org.testng.internal.ConfigInvoker.invokeConfigurations(ConfigInvoker.java:302)
at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:176)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:122)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.testng.TestRunner.privateRun(TestRunner.java:766)
at org.testng.TestRunner.run(TestRunner.java:587)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
at org.testng.SuiteRunner.run(SuiteRunner.java:286)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1187)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1109)
at org.testng.TestNG.runSuites(TestNG.java:1039)
at org.testng.TestNG.run(TestNG.java:1007)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
Caused by: java.lang.NoClassDefFoundError: cucumber/api/event/ConcurrentEventListener
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:855)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:753)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:676)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:634)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:182)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:519)
at io.cucumber.core.options.PluginOption.parsePluginName(PluginOption.java:137)
... 32 more
Caused by: java.lang.ClassNotFoundException: cucumber.api.event.ConcurrentEventListener
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:636)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:182)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:519)
... 42 more
===============================================
Default test
Tests run: 0, Failures: 0, Skips: 0
Configuration Failures: 1, Skips: 0
===============================================
2022-08-04 00:45:48 INFO Log:40 - Database connection closed - AfterSuite TestNG
===============================================
Default suite
Total tests run: 0, Passes: 0, Failures: 0, Skips: 0
Configuration Failures: 1, Skips: 0
===============================================
[TestNG] No tests found. Nothing was run
Usage: <main class> [options] The XML suite files to run
Options:
-alwaysrunlisteners
Should MethodInvocation Listeners be run even for skipped methods
Default: true
-configfailurepolicy
Configuration failure policy (skip or continue)
-d
Output directory
-dataproviderthreadcount
Number of threads to use when running data providers
-dependencyinjectorfactory
The dependency injector factory implementation that TestNG should use.
-excludegroups
Comma-separated list of group names to exclude
-groups
Comma-separated list of group names to be run
-junit
JUnit mode
Default: false
-listener
List of .class files or list of class names implementing ITestListener
or ISuiteListener
-methods
Comma separated of test methods
Default: []
-methodselectors
List of .class files or list of class names implementing IMethodSelector
-mixed
Mixed mode - autodetect the type of current test and run it with
appropriate runner
Default: false
-objectfactory
List of .class files or list of class names implementing
ITestRunnerFactory
-parallel
Parallel mode (methods, tests or classes)
Possible Values: [tests, methods, classes, instances, none, true, false]
-port
The port
-reporter
Extended configuration for custom report listener
-suitename
Default name of test suite, if not specified in suite definition file or
source code
-suitethreadpoolsize
Size of the thread pool to use to run suites
Default: 1
-testclass
The list of test classes
-testjar
A jar file containing the tests
-testname
Default name of test, if not specified in suitedefinition file or source
code
-testnames
The list of test names to run
-testrunfactory, -testRunFactory
The factory used to create tests
-threadcount
Number of threads to use when running tests in parallel
-threadpoolfactoryclass
The threadpool executor factory implementation that TestNG should use.
-usedefaultlisteners
Whether to use the default listeners
Default: true
-log, -verbose
Level of verbosity
-xmlpathinjar
The full path to the xml file inside the jar file (only valid if
-testjar was specified)
Default: testng.xml