Selenium and Cucumber JVM 4 Parallel Execution using ThreadLocal WebDriver and PicoContainer

NEW Posts – Generating Spark and Pdf Extent Report for “Rest Assured with Maven plugin” and “Rest Assured and Cucumber with Maven plugin”

Introduction

Cucumber-JVM 4 supports parallel execution across threads out of the box and also with JUnit and TestNG. The easiest way to integrate Selenium with Cucumber in parallel mode is to use Before and After hooks to create and close the driver respectively. But this is expensive and time consuming.

This article will look at allocating a driver to a specific thread and using it for all the scenarios assigned to the thread. The driver will only be closed at the end of the test execution. The drivers will be stored in a ThreadLocal object. Cucumber implementation of PicoContainer will be used for creating and sharing objects.

Source Code

The source code for JUnit is located here. The source code for TestNG is located here.

DriverFactory Class

The DriverFactory (JUnit/TestNG) class contains the static ThreadLocal field which stores the drivers created for each thread. Below is a brief description of ThreadLocal class from the Java 8 API.

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread.

The DriverFactory class contains static methods to return the driver for a thread, add driver to the ThreadLocal field and remove driver from the ThreadLocal field. This also contains a JVM shutdown hook to quit all the driver instances.

To access the driver for a thread in a StepDefinition or PageObject class, DriverFactory.getDriver() is used.

SharedDriver Class

The SharedDriver (JUnit/TestNG) class contains the logic for creating the concrete driver object and adding the driver to the ThreadLocal field of the DriverFactory. Before a new driver is created a check is performed to verify if a driver for the thread already exists. The main purpose of this class is to allow PicoContainer to instantiate the driver.

StepDefinition Class

Cucumber implementation of PicoContainer uses constructor injection. The StepDefinition (JUnit/TestNG) constructor should have a SharedDriver object as the first parameter followed by PageObject object parameters, that the class requires. These objects will be created and injected into the StepDefinition object.

For each scenario and each row of a scenariooutline, new instance of all step defintion and hook classes are created. If multiple step definition classes have the same class(es) injected into their constructor, then the same instance of these objects are injected into all the step definition objects.

JUnit Runner

When using JUnit in parallel mode, all scenarios in a feature file will be executed in the same thread. The two scenarios in feature1.feature file will be executed in one browser. The single feature2.feature will be executed by another thread in a separate browser.

Maven Failsafe plugin will be used for parallel execution. Refer to the POM for configuration details. Maven Surefire plugin can also be used for parallel execution.

For more details about parallel execution in JUnit refer to this article.

TestNG Runner

When using TestNG in parallel mode, scenarios can be executed in separate threads irrespective of which feature file it belongs too. Different rows in a scenario outline can be also executed in separate threads. The two scenarios in feature1.feature file will be executed by two threads in two browsers. The single feature2.feature will be executed by another thread in a separate browser.

Maven Failsafe plugin will be used for parallel execution. Refer to the POM for configuration details. Maven Surefire plugin can also be used for parallel execution.

For more details about parallel execution in TestNG refer to this article.

Maven Execution

The POM needs to be executed using the Maven command “mvn clean install” or a similar one which executes the maven failsafe plugin integration-test phase.

80 thoughts on “Selenium and Cucumber JVM 4 Parallel Execution using ThreadLocal WebDriver and PicoContainer”

  1. Sir can you please advise as what may be triggering the null

    Using Juni5+Cucumber7

    public class TestContext {
    private PageObjectManager pageObjectManager;
    public ScenarioContext scenarioContext;

    private static final Logger logger = Logger.getLogger(TestContext.class);
    public TestContext() throws InterruptedException {
    pageObjectManager = new PageObjectManager(DriverFactory.getDriver());
    scenarioContext = new ScenarioContext();
    }
    }

    public class PageObjectManager {
    private WebDriver driver;
    public PageObjectManager(WebDriver driver) {
    if (driver == null) {
    throw new IllegalArgumentException(“Driver cannot be null.”);
    }
    this.driver = driver;
    }
    }
    public class DriverFactory {
    private static final ThreadLocal tlDriver = new ThreadLocal();
    public WebDriver init_driver(String browser) {
    if (browser.equals(“chrome”)) {
    tlDriver.set(new ChromeDriver(options));
    }
    else if (browser.equals(“safari”)) {
    tlDriver.set(new SafariDriver());
    } else {
    System.out.println(“Please pass the correct browser value: ” + browser);
    }
    }
    return getDriver();
    }

    public static WebDriver getDriver() {
    return tlDriver.get();
    }
    }

    Hooks
    public class Hooks {
    private DriverFactory driverFactory;
    private WebDriver driver;
    @Before(order = 1)
    //@BeforeEach
    public void getProperty() throws InterruptedException {
    ExtentReport.setExtentReport();
    configReader = new ConfigFileReader();
    prop = configReader.init_prop();
    String browserName = prop.getProperty(“Browser”);
    driverFactory = new DriverFactory();
    driver = driverFactory.init_driver(browserName);
    String url = prop.getProperty(“Environment”);
    if(url.equals(“sandbox”))
    {
    driver.get(prop.getProperty(“QA”));
    }
    }

    Using mvn clean install -Dmaven.surefire.debug
    Console error shows below >>> at PageObjectManager.java
    java.lang.IllegalArgumentException: Driver cannot be null.
    at managers.PageObjectManager.(PageObjectManager.java:39)
    at util.TestContext.(TestContext.java:18)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.picocontainer.injectors.AbstractInjector.newInstance(AbstractInjector.java:145)
    at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:342)

    Can you please share me git link for parallel execution using Threadlocal Junit for reference
    Thanks
    VS

    1. You do not need to inject the driver in your pageobjmgr class or anywhere else. Just use DriverFactory.getDriver().

      1. Sir with continuation I have implemented Junit5+ Cuc to run scenarios in parallel.
        However need advise on case
        1) What I have scene is if due to some reason if the browser does not quit (thread) only 2 scenarios which get executed will show up in report (cucumber.execution.parallel.config.fixed.parallelism=2)
        Lets say 20 scenarios then only 2 show status as passed and rest will be marked as failed even though when run in nonheadless mode I can see browser closing and opening as per test cases.
        2) How can we scenarios update the report independently
        How do I handle this report being created or impact of 1 thread preventing report
        public class DriverFactoryMy {
        public static ThreadLocal tldriver = new ThreadLocal();

        public static WebDriver getdriver()
        {
        if (tldriver.get() == null) {
        tldriver.set(createDriver(browserName));
        logger.info(“New WebDriver instance created for thread {}”, Thread.currentThread().getId());
        }

        return tldriver.get();
        }

        public static WebDriver getDriverInstance() {
        return tldriver.get();
        }

        public static void quitdriver() {
        logger.info(“Driver Quit performed”);
        if (tldriver.get() != null) {
        tldriver.get().quit();
        tldriver.remove();
        }
        }

        private static WebDriver createDriver(String browser) {
        logger.info(“Browser value is: {}”, browser);
        WebDriver driver = null;
        if (browser.equals(“chrome”)) {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver(options);
        } else {
        logger.error(“Please pass the correct browser value: {}”, browser);
        }
        return driver;
        }

        }

        //Testcontext
        public TestContext() throws InterruptedException {
        pageObjectManager = new PageObjectManager(DriverFactoryMy.tldriver);
        scenarioContext = new ScenarioContext();
        }
        Thanks Vaibhav

        1. If you are using the extent adapter there it is not dependent on thread quitting or not. It uses the cucumber plugin events.
          If you are managing extent on your own then you can try with a java shutdown hook which will close all open browser windows at the end. But I still do not get why report is not generated if browser are open.

          1. No Sir in POM I have 1.7.0 , extent report was causing issue on Azure I commented out that and kept only the above. The report will get created Sir but post that 1 thread which gets hanged all will be marked as failed. After reading I did add logic to check for thread status try {
            Thread.currentThread().interrupt();
            System.out.println(“Thread has been interrupted…”);
            tldriver.get().quit();
            tldriver.set(createDriver(prop.getProperty(“Browser”)));
            System.out.println(“WebDriver instance restarted for thread :” + Thread.currentThread().getId());
            logger.info(“WebDriver instance restarted for thread “, Thread.currentThread().getId());
            shouldExit = true;
            } catch (Exception e) {
            and saw in logs
            Thread has been interrupted…
            WebDriver instance restarted for thread :20 but still same.
            I am blocked from last 1 week can you please advise

            Thanks VS

  2. Hello Sir,

    I need assistance as I am blocked from 2 days for POC for parallelism (Junit5+Cuc7)
    Raised query here too
    https://stackoverflow.com/questions/75829934/cucumber-bdd-scenarios-to-run-in-parallel-on-azure-selfhosted-agent-junit5cucu
    Junit4+ Cucumber 6 > Sequential scenarios are executed – Ok
    In the current framework we have below —
    Hooks
    @Before(order = 1)
    public void getProperty() {
    ExtentReport.setExtentReport();
    public class BaseClass { // variable defined
    public static ExtentTest loggerE;
    … }

    public class ExtentReport extends BaseClass {
    public static void setExtentReport() {
    loggerE=extent.startTest(tDate); // this line gives Null Pointer as seen in job logs on
    …}

    Commented out the loggerE and I get the below

    2023-03-24T16:53:35.5671195Z [INFO] ——————————————————-
    2023-03-24T16:53:35.5671625Z [INFO] T E S T S
    2023-03-24T16:53:35.5671922Z [INFO] ——————————————————-
    2023-03-24T16:53:37.4620327Z [INFO] Running testrunners.RunCucumberTest
    2023-03-24T16:53:41.7439805Z
    2023-03-24T16:53:41.7446854Z @LeadRegression @CreateLeadWithSc
    2023-03-24T16:53:41.7449710Z Scenario Outline: TC001_CreateLead: Login as a “Srabanti Gupta” and Create a lead with contact type “Email” “WhatMarketingSource” and verify lead was create # Features/Lead2.feature:52
    2023-03-24T16:53:41.7450610Z
    2023-03-24T16:53:41.7451405Z @LeadRegression @CreateLeadWithSc
    2023-03-24T16:53:41.7452562Z Scenario Outline: TC001_CreateLead: Login as a “Srabanti Gupta” and Create a lead with contact type “Email” “WhatMarketingSource” and verify lead was create # Features/Lead.feature:52
    2023-03-24T16:53:41.7489960Z log4j:WARN No appenders could be found for logger (stepDefinitions.LoginStep). Given Launch the browser and navigate to SF login page # stepDefinitions.LoginStep.launch_the_browser_and_navigate_to_sf_login_page()
    2023-03-24T16:53:41.7494599Z Given Launch the browser and navigate to SF login page # stepDefinitions.LoginStep.launch_the_browser_and_navigate_to_sf_login_page()
    2023-03-24T16:53:41.7496093Z
    2023-03-24T16:53:41.7496840Z log4j:WARN No appenders could be found for logger (stepDefinitions.LoginStep).
    2023-03-24T16:53:41.7498739Z log4j:WARN Please initialize the log4j system properly.
    2023-03-24T16:53:41.7500156Z log4j:WARN Please initialize the log4j system properly.
    2023-03-24T16:53:41.7502840Z log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    2023-03-24T16:53:41.7504762Z log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    2023-03-24T16:53:41.7506094Z java.lang.NullPointerException
    2023-03-24T16:53:41.7507750Z at java.base/java.util.Objects.requireNonNull(Objects.java:221)
    2023-03-24T16:53:41.7510203Z at org.openqa.selenium.support.ui.FluentWait.(FluentWait.java:106)
    2023-03-24T16:53:41.7512507Z at org.openqa.selenium.support.ui.FluentWait.(FluentWait.java:97)
    2023-03-24T16:53:41.7513640Z at util.GenericUtilities.fluientWaitforElementTobePresent(GenericUtilities.java:1210)
    2023-03-24T16:53:41.7515583Z at pageObjects.LoginPage.getLoginPageTitleName(LoginPage.java:250)
    2023-03-24T16:53:41.7518184Z at stepDefinitions.LoginStep.user_should_navigate_to_SF_login_page(LoginStep.java:117)
    2023-03-24T16:53:41.7521624Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    2023-03-24T16:53:41.7524246Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    2023-03-24T16:53:41.7537134Z at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    2023-03-24T16:53:41.7544141Z at java.base/java.lang.reflect.Method.invoke(Method.java:566)

    Note:* – I have used
    public static ThreadLocal tlDriver = new ThreadLocal();

    public static synchronized WebDriver getDriver() {
    return tlDriver.get();
    }

    Can you please advise as what may causing null pointer when Job is executed on Azure
    The selfhosted agent Pool can be scaled up for parallelism.
    Do you have references for Parallelism on azure pipeline

    Thanks
    Vaibhav

    1. Where and when is the ‘extent’ variable initialized? Also when is the ExtentReport class initialized?

      Parallelism and static is a dangerous combination. Why don’t you use the cucumber adapter instead of handling the headache of extentreport code inside tests?

      1. Sir the extent report is coming in picture in hooks (this was implemented existing framework)
        @Before(order = 1)
        public void getProperty() {
        ExtentReport.setExtentReport(); ….
        }
        public class ExtentReport extends BaseClass {
        private static final Logger logger = Logger.getLogger(ExtentReport.class);
        public static void setExtentReport() {
        } ….
        Base Class has public static ExtentReports extent; //defined
        I commented out the code extentreport call and I get the below error in logs

        2023-03-26T15:05:49.9062225Z java.lang.NullPointerException
        2023-03-26T15:05:49.9064628Z at stepDefinitions.LoginStep.launch_the_browser_and_navigate_to_sf_login_page(LoginStep.java:42)
        2023-03-26T15:05:49.9066545Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        2023-03-26T15:05:49.9068613Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        2023-03-26T15:05:49.9070511Z at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        2023-03-26T15:05:49.9074965Z at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        2023-03-26T15:05:49.9077356Z at io.cucumber.java.Invoker.doInvoke(Invoker.java:66)
        2023-03-26T15:05:49.9079793Z at io.cucumber.java.Invoker.invoke(Invoker.java:24)
        2023-03-26T15:05:49.9083213Z at io.cucumber.java.AbstractGlueDefinition.invokeMethod(AbstractGlueDefinition.java:47)
        2023-03-26T15:05:49.9086407Z at io.cucumber.java.JavaStepDefinition.execute(JavaStepDefinition.java:29)
        2023-03-26T15:05:49.9095106Z at io.cucumber.core.runner.CoreStepDefinition.execute(CoreStepDefinition.java:66)
        2023-03-26T15:05:49.9096746Z at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:63)
        2023-03-26T15:05:49.9097788Z at io.cucumber.core.runner.ExecutionMode$1.execute(ExecutionMode.java:10)
        2023-03-26T15:05:49.9098701Z at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:85)
        2023-03-26T15:05:49.9099568Z at io.cucumber.core.runner.TestStep.run(TestStep.java:57)
        2023-03-26T15:05:49.9100472Z at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:51)
        2023-03-26T15:05:49.9101369Z at io.cucumber.core.runner.TestCase.run(TestCase.java:84)
        2023-03-26T15:05:49.9102181Z at io.cucumber.core.runner.Runner.runPickle(Runner.java:75)
        2023-03-26T15:05:49.9103286Z at io.cucumber.junit.platform.engine.CucumberEngineExecutionContext.lambda$runTestCase$4(CucumberEngineExecutionContext.java:112)
        2023-03-26T15:05:49.9104550Z at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$5(CucumberExecutionContext.java:129)
        2023-03-26T15:05:49.9105768Z at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
        2023-03-26T15:05:49.9106958Z at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:129)
        2023-03-26T15:05:49.9108197Z at io.cucumber.junit.platform.engine.CucumberEngineExecutionContext.runTestCase(CucumberEngineExecutionContext.java:109)
        2023-03-26T15:05:49.9109803Z at io.cucumber.junit.platform.engine.PickleDescriptor.execute(PickleDescriptor.java:100)
        2023-03-26T15:05:49.9111158Z at io.cucumber.junit.platform.engine.PickleDescriptor.execute(PickleDescriptor.java:29)
        2023-03-26T15:05:49.9115936Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
        2023-03-26T15:05:49.9117301Z at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        2023-03-26T15:05:49.9118564Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        2023-03-26T15:05:49.9119744Z at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        2023-03-26T15:05:49.9120919Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        2023-03-26T15:05:49.9122198Z at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        2023-03-26T15:05:49.9123710Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        2023-03-26T15:05:49.9125345Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        2023-03-26T15:05:49.9136615Z at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:202)
        2023-03-26T15:05:49.9139527Z at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:146)
        2023-03-26T15:05:49.9141028Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        2023-03-26T15:05:49.9142311Z at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        2023-03-26T15:05:49.9143567Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        2023-03-26T15:05:49.9144697Z at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        2023-03-26T15:05:49.9145847Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        2023-03-26T15:05:49.9147044Z at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        2023-03-26T15:05:49.9148300Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        2023-03-26T15:05:49.9149489Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        2023-03-26T15:05:49.9150895Z at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:202)
        2023-03-26T15:05:49.9154853Z at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:146)
        2023-03-26T15:05:49.9156119Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        2023-03-26T15:05:49.9157561Z at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        2023-03-26T15:05:49.9158584Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        2023-03-26T15:05:49.9159654Z at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        2023-03-26T15:05:49.9161008Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        2023-03-26T15:05:49.9162330Z at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        2023-03-26T15:05:49.9170414Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        2023-03-26T15:05:49.9171886Z at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        2023-03-26T15:05:49.9173371Z at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:202)
        2023-03-26T15:05:49.9174757Z at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
        2023-03-26T15:05:49.9175748Z at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
        2023-03-26T15:05:49.9176774Z at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
        2023-03-26T15:05:49.9177766Z at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
        2023-03-26T15:05:49.9185882Z at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
        2023-03-26T15:05:49.9187022Z at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)

        Can you please advise as what may be causing this.
        Please Note* – This comes up only on Selfhosted agent when run is initiated
        Is some prerequisite missing on the agent?

        Thanks
        Vaibhav

      2. Sir I changed some dependencies still getting the below

        2023-03-26T17:48:53.3157404Z [INFO]
        2023-03-26T17:48:53.3157966Z [INFO] ——————————————————-
        2023-03-26T17:48:53.3158274Z [INFO] T E S T S
        2023-03-26T17:48:53.3158564Z [INFO] ——————————————————-
        2023-03-26T17:48:54.4339669Z Mar 26, 2023 5:48:54 PM io.cucumber.junit.platform.engine.DiscoverySelectorResolver warnWhenCucumberFeaturesPropertyIsUsed
        2023-03-26T17:48:54.4341290Z WARNING: Discovering tests using the cucumber.features property. Other discovery selectors are ignored!
        2023-03-26T17:48:54.4341861Z Please request/upvote/sponsor/ect better support for JUnit 5 discovery selectors.
        2023-03-26T17:48:54.4342262Z See: https://github.com/cucumber/cucumber-jvm/pull/2498
        2023-03-26T17:48:54.4350231Z [ERROR] TestEngine with ID ‘cucumber’ failed to discover tests
        2023-03-26T17:48:54.5000971Z [INFO]
        2023-03-26T17:48:54.5001401Z [INFO] Results:
        2023-03-26T17:48:54.5001622Z [INFO]
        2023-03-26T17:48:54.5026717Z [INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
        2023-03-26T17:48:54.5027336Z [INFO]
        2023-03-26T17:48:54.5266548Z [INFO] ————————————————————————
        2023-03-26T17:48:54.5267195Z [INFO] BUILD FAILURE
        2023-03-26T17:48:54.5267538Z [INFO] ————————————————————————
        2023-03-26T17:48:54.5301649Z [INFO] Total time: 10.661 s
        2023-03-26T17:48:54.5303692Z [INFO] Finished at: 2023-03-26T17:48:54Z
        2023-03-26T17:48:54.5304373Z [INFO] ————————————————————————
        2023-03-26T17:48:54.5315787Z [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M5:test (default-test) on project MTH_SF_CRM: There are test failures.
        2023-03-26T17:48:54.5316790Z [ERROR]
        2023-03-26T17:48:54.5317417Z [ERROR] Please refer to C:\a\1\s\target\surefire-reports for the individual test results.
        2023-03-26T17:48:54.5318305Z [ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
        2023-03-26T17:48:54.5319077Z [ERROR] There was an error in the forked process
        2023-03-26T17:48:54.5319699Z [ERROR] TestEngine with ID ‘cucumber’ failed to discover tests
        2023-03-26T17:48:54.5320522Z [ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: There was an error in the forked process
        2023-03-26T17:48:54.5321295Z [ERROR] TestEngine with ID ‘cucumber’ failed to discover tests
        2023-03-26T17:48:54.5323307Z [ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:733)
        2023-03-26T17:48:54.5324508Z [ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:305)
        2023-03-26T17:48:54.5325688Z [ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:265)
        2023-03-26T17:48:54.5326952Z [ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1314)
        2023-03-26T17:48:54.5328372Z [ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1159)
        2023-03-26T17:48:54.5329748Z [ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:932)
        2023-03-26T17:48:54.5331072Z [ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:126)
        2023-03-26T17:48:54.5332334Z [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2(MojoExecutor.java:342)
        2023-03-26T17:48:54.5333507Z [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute(MojoExecutor.java:330)
        2023-03-26T17:48:54.5334699Z [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:213)
        2023-03-26T17:48:54.5335838Z [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:175)
        2023-03-26T17:48:54.5337191Z [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.access$000(MojoExecutor.java:76)
        2023-03-26T17:48:54.5338343Z [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor$1.run(MojoExecutor.java:163)
        2023-03-26T17:48:54.5339563Z [ERROR] at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute(DefaultMojosExecutionStrategy.java:39)
        2023-03-26T17:48:54.5340801Z [ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:160)
        2023-03-26T17:48:54.5342229Z [ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:105)
        2023-03-26T17:48:54.5343589Z [ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:73)
        2023-03-26T17:48:54.5345010Z [ERROR] at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:53)
        2023-03-26T17:48:54.5346360Z [ERROR] at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:118)
        2023-03-26T17:48:54.5347451Z [ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:260)
        2023-03-26T17:48:54.5348457Z [ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:172)
        2023-03-26T17:48:54.5349447Z [ERROR] at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:100)
        2023-03-26T17:48:54.5350399Z [ERROR] at org.apache.maven.cli.MavenCli.execute(MavenCli.java:821)
        2023-03-26T17:48:54.5351348Z [ERROR] at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:270)
        2023-03-26T17:48:54.5352287Z [ERROR] at org.apache.maven.cli.MavenCli.main(MavenCli.java:192)
        2023-03-26T17:48:54.5353222Z [ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        2023-03-26T17:48:54.5354340Z [ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        2023-03-26T17:48:54.5355654Z [ERROR] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        2023-03-26T17:48:54.5356764Z [ERROR] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        2023-03-26T17:48:54.5357818Z [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
        2023-03-26T17:48:54.5359436Z [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
        2023-03-26T17:48:54.5361555Z [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
        2023-03-26T17:48:54.5362536Z [ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)

        Note*- These are job logs of the agenet

  3. Hi Mounish,

    my cucumber Junit framework Driverfactory is almost like you shared in example but when I’m running feature files in parallel using maven surefire I’m getting below error in most of the scenarios:-
    org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?

    Can you suggest any solution or workaround?

    1. Figure out where the quit calls are being made? Are u quitting the webdriver on failure and not removing it from the factory?
      Sharing your code in a repo would be easier to figure out a solution. Thx

      1. I gave you access to my repo on git. could you please check the driverfactory code and share your analysis? Thanks

  4. Hi Mounish,

    When I tried to implement this in my project, I’m getting this error

    Cannot invoke “Object.toString()” because the return value of “java.util.Map.get(Object)” is null

    browser is opened and closed immediately. Earlier, I tried to implement just using surefire and Junit, for some reason when two browsers opened execution happened in one browser only. and now, I’m getting this. can you help?

      1. Hi Mounish,
        I’m using
        6.1.1
        4.0.0-beta-1

        If I use 4.4.0, I’m getting a different issue, that’s why changed to this version. Here are the stacktrace:

        ——————————————————————————-
        Test set: com.runnerClasses.Outplay_ParallelRunnerClassTest
        ——————————————————————————-
        Tests run: 2, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 9.799 sec <<< FAILURE!
        User login – Prospects Screen(Prospects – create, Search, Tags) Time elapsed: 4.129 sec <<< ERROR!
        org.openqa.selenium.SessionNotCreatedException: Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure.
        Build info: version: '4.0.0-beta-1', revision: '9c03156c2b'
        System info: host: 'FAROOQ', ip: '192.168.1.26', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '15.0.1'
        Driver info: org.openqa.selenium.chrome.ChromeDriver
        Command: [null, newSession {desiredCapabilities=Capabilities {browserName: chrome}}]
        Capabilities {}
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:635)
        at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:252)
        at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:174)
        at org.openqa.selenium.chromium.ChromiumDriver.(ChromiumDriver.java:82)
        at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:99)
        at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:86)
        at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:41)
        at driver.SharedDriver.(SharedDriver.java:13)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
        at org.picocontainer.injectors.AbstractInjector.newInstance(AbstractInjector.java:145)
        at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:342)
        at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
        at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
        at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
        at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
        at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
        at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:632)
        at org.picocontainer.parameters.BasicComponentParameter$1.resolveInstance(BasicComponentParameter.java:118)
        at org.picocontainer.parameters.ComponentParameter$1.resolveInstance(ComponentParameter.java:136)
        at org.picocontainer.injectors.SingleMemberInjector.getParameter(SingleMemberInjector.java:78)
        at org.picocontainer.injectors.ConstructorInjector$CtorAndAdapters.getParameterArguments(ConstructorInjector.java:309)
        at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:335)
        at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
        at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
        at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
        at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
        at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
        at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)
        at io.cucumber.picocontainer.PicoFactory.getInstance(PicoFactory.java:49)
        at io.cucumber.java.AbstractGlueDefinition.invokeMethod(AbstractGlueDefinition.java:44)
        at io.cucumber.java.JavaStepDefinition.execute(JavaStepDefinition.java:29)
        at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:63)
        at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:92)
        at io.cucumber.core.runner.TestStep.run(TestStep.java:63)
        at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:49)
        at io.cucumber.core.runner.TestCase.run(TestCase.java:98)
        at io.cucumber.core.runner.Runner.runPickle(Runner.java:71)
        at io.cucumber.junit.PickleRunners$NoStepDescriptions.run(PickleRunners.java:140)
        at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:118)
        at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:24)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at io.cucumber.junit.Cucumber.runChild(Cucumber.java:192)
        at io.cucumber.junit.Cucumber.runChild(Cucumber.java:88)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at io.cucumber.junit.Cucumber$RunCucumber.evaluate(Cucumber.java:227)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
        Caused by: java.lang.NullPointerException: Cannot invoke “Object.toString()” because the return value of “java.util.Map.get(Object)” is null
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:122)
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:73)
        at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:153)
        at org.openqa.selenium.remote.service.DriverCommandExecutor.invokeExecute(DriverCommandExecutor.java:153)
        at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:128)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:620)
        … 76 more

        User login – Prospects Screen(Prospects – Mark as Finished, Pause, Optout, Delete) Time elapsed: 1.935 sec <<< ERROR!
        org.openqa.selenium.SessionNotCreatedException: Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure.
        Build info: version: '4.0.0-beta-1', revision: '9c03156c2b'
        System info: host: 'FAROOQ', ip: '192.168.1.26', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '15.0.1'
        Driver info: org.openqa.selenium.chrome.ChromeDriver
        Command: [null, newSession {desiredCapabilities=Capabilities {browserName: chrome}}]
        Capabilities {}
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:635)
        at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:252)
        at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:174)
        at org.openqa.selenium.chromium.ChromiumDriver.(ChromiumDriver.java:82)
        at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:99)
        at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:86)
        at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:41)
        at driver.SharedDriver.(SharedDriver.java:13)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
        at org.picocontainer.injectors.AbstractInjector.newInstance(AbstractInjector.java:145)
        at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:342)
        at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
        at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
        at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
        at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
        at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
        at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:632)
        at org.picocontainer.parameters.BasicComponentParameter$1.resolveInstance(BasicComponentParameter.java:118)
        at org.picocontainer.parameters.ComponentParameter$1.resolveInstance(ComponentParameter.java:136)
        at org.picocontainer.injectors.SingleMemberInjector.getParameter(SingleMemberInjector.java:78)
        at org.picocontainer.injectors.ConstructorInjector$CtorAndAdapters.getParameterArguments(ConstructorInjector.java:309)
        at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:335)
        at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
        at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
        at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
        at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
        at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
        at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
        at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)
        at io.cucumber.picocontainer.PicoFactory.getInstance(PicoFactory.java:49)
        at io.cucumber.java.AbstractGlueDefinition.invokeMethod(AbstractGlueDefinition.java:44)
        at io.cucumber.java.JavaStepDefinition.execute(JavaStepDefinition.java:29)
        at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:63)
        at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:92)
        at io.cucumber.core.runner.TestStep.run(TestStep.java:63)
        at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:49)
        at io.cucumber.core.runner.TestCase.run(TestCase.java:98)
        at io.cucumber.core.runner.Runner.runPickle(Runner.java:71)
        at io.cucumber.junit.PickleRunners$NoStepDescriptions.run(PickleRunners.java:140)
        at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:118)
        at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:24)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at io.cucumber.junit.Cucumber.runChild(Cucumber.java:192)
        at io.cucumber.junit.Cucumber.runChild(Cucumber.java:88)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at io.cucumber.junit.Cucumber$RunCucumber.evaluate(Cucumber.java:227)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
        Caused by: java.lang.NullPointerException: Cannot invoke “Object.toString()” because the return value of “java.util.Map.get(Object)” is null
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:122)
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:73)
        at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:153)
        at org.openqa.selenium.remote.service.DriverCommandExecutor.invokeExecute(DriverCommandExecutor.java:153)
        at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:128)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:620)
        … 76 more

        1. Hi I will need to try this out before I can find a solution. Will give it a shot in a couple of days. Thx.

  5. Hi Mounish,
    In my framework, I’m using TestNG with Cucumber and Java. If I use Cucumber-jvm-parallel-plugin I can execute scripts parallelly but I can’t use failedRunner.txt o run all my failed test cases automatically.
    If I use my runner class using maven-surefire-plugin or failsafe-plugin, all my test gets executed in the same thread and fails.
    Even. if I try to run my failed runner class from cli, the fail features are not found and throws no future found at the provided destination (@target/rerun.txt)
    If you provide your email I can share my driver and pom with you.
    I have tried so many places, but haven’t got any useful reply. I hope I’ll get my reply here.

  6. The above implementation of parallel cucumber tests using TestNG, can you please help me with gradle instead of pom.xml?

    1. Will have a look into this, though I have a limited exposure to gradle. But I think cucumber has a limited support for gradle out of the box, I may be wrong.

        1. Thanks Mounish, and sorry for late response. Yes I was able to add dependencies using gradle in similar way as documentation you have provided.
          But my challenge is with failsafe plugin execution and goals. I am yet to find that solution to execute in parallel with gradle.
          If you have any resources that you can share, would be a great help.

  7. How do you close the driver without affecting the other tests?
    Example : I am running a parallel test suite , but If do a `DriverFactory.getDriver().close` the other session gets affected.

  8. Hi
    Iam using Maven Project with Page object model and Page Factory. I Declare Webdriver as static for pagfe factory.If i use parallel Execution it opens the browser parallely but the test happens in single browser .Can You Resolve it or any other ideas are welcomed .
    Thank You

    1. Static variables and parallel execution will always cause problems. U could try out the implementation used in this article instead.

  9. Hi Mounish,

    Thanks a lot for this wonderful article.
    I have a basic question – Although there is static block in DriverFactory class, when tests are run, the control first comes to constructor of SharedDriver class. I tried to understand how this is being done by debugging, but couldn’t figure out.
    Could you please clarify how that is happening?

    1. Adding to above comment:
      Depending on number of scenarios we are running, control comes to constructor of SharedDriver class, from where it invokes chrome. Just curious to know how that is being done. Thanks!

      1. Cucumber-picocontainer instantiates all the classes which are present in the constructor arguments of step definition classes. When it comes across SharedDriver it calls it’s constructor which checks if the current thread already has a driver instance in the ThreadLocal variable of the DriverFactory class. If there is no existing driver instance then it creates one. So for the whole test execution the ‘if block driver instantiation code’ should only be executed once for a specific thread. This is true unless u remove the driver instance in the code maybe due to an exception and u want a fresh driver. For more details on picocontainer in cucumber-jvm refer to this – https://ghauto.tech/1496/

        1. Hi Mounish,
          Thank you for the response.
          Im trying to include your above code to my framework, but Im facing issues with it.
          Suppose there are 2 scenarios with first step in each scenario is login to application, when I ran the tests, credentials for both tests are entered in one single chrome instance instead of doing it on other instance. That is suppose username is ‘admin’, text ‘adminadmin’ gets entered in one chrome instance & other chrome instance just stay as it is after launch.
          I guess Im doing some thing wrong with driver object. Could you please have a look at my code & help me out?
          Could you please drop an email so that I can send you my code.
          Thanks a ton.

          1. This happens when u r using static somewhere for ur driver variable. static and threads do not like each other. Dropped u an email on the id provided.

        2. Hi Mounish,
          Thank you for the response.
          Im trying to include your code in my framework to implement parallel test execution. But Im facing some issues with it.
          Suppose there are 2 scenarios in which first step on both the scenario is to login to application.When these 2 tests are run, 2 chrome instances gets launched, But the login credentials for both scenarios gets added in one chrome instance. That is for example when I pass ‘admin’ as username, text “adminadmin” gets entered in one chrome instance & other chrome instance remains as it is after launch after hitting application URL. Here actually both scenarios are getting executed in same thread or same chrome instance. I guess Im doing some thing wrong in handling driver object.
          Could you please have a look at my code & help me out.
          Could you please drop me an email so that I can share my code.

  10. Is there a way to Close browsers safely? I added this class in my suite but whenever I try to “close” a browser I am getting an invalud session ID.

    “` org.openqa.selenium.NoSuchSessionException: invalid session id
    Build info: version: ‘3.141.59’, revision: ‘e82be7d358’, time: ‘2018-11-14T08:17:03’ “`

    here’s my method to close

    “` public void closeCustomerDisplay() {
    String winHandleBefore = DriverFactory.getDriver().getWindowHandle();
    for (String winHandle : DriverFactory.getDriver().getWindowHandles()) {
    DriverFactory.getDriver().switchTo().window(winHandle);
    DriverFactory.getDriver().close();
    }
    DriverFactory.getDriver().switchTo().window(winHandleBefore);
    }
    “`

    1. Which line is throwing the exception, the close or the switchto statement? Have u removed the check for not closing the ‘before’ window handle in the for loop when u copied the code here? Else the for loop will close all windows for the driver instance and dispose of the instance.

  11. How to make an scenario dependent on another in that case.

    Now suppose we are running an feature file in parallel using TestNG and we are doing a simple CRUD operation.
    Now my feature 1 file

    1st scenario create a user with some details
    2nd scenario edit a user details

    As per the guideline:

    When using TestNG in parallel mode, scenarios can be executed in separate threads irrespective of which feature file it belongs too. Different rows in a scenario outline can be also executed in separate threads. The two scenarios in feature1.feature file will be executed by two threads in two browsers. The single feature2.feature will be executed by another thread in a separate browser.

    Now if thats the case as described above and my above example run parallely my second case going to fail for sure.
    How to handle then? do I need to switch to Junit just due to same?

  12. Hi, there!
    I’m trying to adapt your DriverFactory to my project. And I figured out that ShutdownHook doesn’t work. I guess this is because I use Cucumber Hooks with @Before and @After methods.
    In @Before method I doing like that
    driverFactory.setDriver(System.getProperty(“browser”));
    driver = DriverFactory.getDriver();
    driver.manage().window().maximize();
    driver.get(propertyHelper.getValue(“baseUrl”));

    And in @After method – quit the browser. I tried to remove this section – no luck. Browser windows still open after tests.
    driver.quit();

    How can I combine properly ShutdownHook from DriverFactory and cucumber hooks? I guess I need to do some updates of Cucumber Runner class? Need help. Please 🙂

    1. Basically u need to move the driver initialization code in the before hook to the SharedDriver constructor other than the driver.get(). U can create a switch method to create the appropriate driver in the constructor. What is the difference between driverFactory object and the DriverFactory class? Is it creating a driver too?

      Similarly the code in after hook should be moved to shutdown hook.

      1. I removed SharedDriver class and moved initialization code to DriverFactory class because I don’t get it how to initialize appropriate driver in the constructor + constructor injection if I set required browser type via System.getProperty(“browser”)…
        The difference between driverFactory object and the DriverFactory class that I combine SharedDriver class with webDriver initialization and DriverFactory class. So it has as static so non-static methods.
        Can I show you my Hooks class and DriverFactory class by mail or by other resources(mby stackoverflow…)? I really interesting figure out the optimal way implementation

    1. U have unnecessary STATIC instance variables and methods in pageobject and stepdefinitions which should be removed. Static and parallel do not work well together at all.
      In pageobjects remove all static occurrences except for the ‘final static String’ fields.
      In stepdefinitions remove all static occurrences.

      Also u should maximize the window when u initialize the driver.

      Even after doing this there is a selenium error
      org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point (1001, 232). Other element would receive the click:
      at stepdef.StepDefinition.click_on_FROM_EDIT(StepDefinition.java:44)
      at ?.User clicks on FROM EDIT(file:src/test/resources/features/feat2.feature:8)
      Try with a wait should be an easy fix.

      1. Hi,
        I removed the STATIC instances as you mentioned from the Pageobjects and Step Definition, but still am facing the same staleElement reference.
        Not Sure where I am missing. Can you please help.
        Thanks,
        KM

          1. Hi Mounish,
            Thanks for the help. It did work for me. A small request, can you please remove the code from the above repository.

            Thanks,
            KM

          2. Hi Mounish,

            I followed about framework and trying make run parallel execution for cucumber framework but i’m getting staleElement reference error.

            I structured same like about code. Could you please me how to resole this issue?

            Thanks,
            Dhatchanamoorthy

          3. Hi Mounish,

            I’m also getting the same error. Actually i’m trying to run parallel execution and followed above structure. But I could not help.

            I’m getting staleElement reference error.

            Could you please help me.

            Thanks.,

          4. Hi Mounish,

            Thank you for replaying back.

            1. Nope!. Driver is not static.
            2. I commented this time driver.quite. Please see below is error message.
            3. Can you share me your email id or github link. So that i’ll share my project.

            org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
            (Session info: chrome=80.0.3987.106)
            For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/stale_element_reference.html
            Build info: version: ‘3.141.59’, revision: ‘e82be7d358’, time: ‘2018-11-14T08:17:03’
            System info: host: ‘SLB-2XQZ7S2’, ip: ‘100.97.130.212’, os.name: ‘Windows 10’, os.arch: ‘amd64’, os.version: ‘10.0’, java.version: ‘1.8.0_201’
            Driver info: org.openqa.selenium.chrome.ChromeDriver
            Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 80.0.3987.106, chrome: {chromedriverVersion: 79.0.3945.36 (3582db32b3389…, userDataDir: C:\Users\DGOVIN~1\AppData\L…}, goog:chromeOptions: {debuggerAddress: localhost:58091}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
            Session ID: acb36c28ad8d1aff8c682159f71e24bf
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
            at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
            at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
            at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
            at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
            at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
            at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
            at org.openqa.selenium.remote.RemoteWebDriver.perform(RemoteWebDriver.java:618)
            at org.openqa.selenium.interactions.Actions$BuiltAction.perform(Actions.java:639)
            at Utilities.CommonFunctions.buildPerform(CommonFunctions.java:307)
            at Utilities.CommonFunctions.moveToEle(CommonFunctions.java:287)
            at PageFactoryElements.OpsActivityDashboard.filterBasedOnLastUpdatedBy(OpsActivityDashboard.java:61)
            at StepDefinition.CreateOpsActivitySD.userNavigatedBrieffromOpsActivityDashboardAndChooseProfile(CreateOpsActivitySD.java:84)
            at ?.the user navigated to Brief page from Operation activity dashboard and choose the profile based on “Bergen WL”(Regression/Feature/Operation management/18_812889_TestBrief.feature:7)

            org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
            (Session info: chrome=80.0.3987.106)
            For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/stale_element_reference.html
            Build info: version: ‘3.141.59’, revision: ‘e82be7d358’, time: ‘2018-11-14T08:17:03’
            System info: host: ‘SLB-2XQZ7S2’, ip: ‘100.97.130.212’, os.name: ‘Windows 10’, os.arch: ‘amd64’, os.version: ‘10.0’, java.version: ‘1.8.0_201’
            Driver info: org.openqa.selenium.chrome.ChromeDriver
            Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 80.0.3987.106, chrome: {chromedriverVersion: 79.0.3945.36 (3582db32b3389…, userDataDir: C:\Users\DGOVIN~1\AppData\L…}, goog:chromeOptions: {debuggerAddress: localhost:58092}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
            Session ID: 5e21e6a53c9a7f52adddc3573e387a0d
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
            at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
            at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
            at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
            at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
            at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
            at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
            at org.openqa.selenium.remote.RemoteWebDriver.executeScript(RemoteWebDriver.java:489)
            at Utilities.CommonFunctions.javascriptClick(CommonFunctions.java:415)
            at PageFactoryElements.OperationManagement.viewDashboardTypes(OperationManagement.java:93)
            at StepDefinition.CreateOpsActivitySD.userNavigatedDeBrieffromOpsActivityDashboardAndChooseProfile(CreateOpsActivitySD.java:60)
            at ?.the user navigated to DeBrief page from Operation activity dashboard and choose the profile based on “Bergen WL”(Regression/Feature/Operation management/19_812910_Debrief.feature:7)

            End Date & Time of Execution – Wed Feb 26 21:03:17 IST 2020
            Total no of Test case passed Percentage – 0
            [ERROR] Tests run: 2, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 244.942 s <<< FAILURE! – in TestSuite
            [ERROR] runScenario(StepDefinition.RunnerIT) Time elapsed: 242.43 s <<< FAILURE!
            org.openqa.selenium.StaleElementReferenceException:
            stale element reference: element is not attached to the page document
            (Session info: chrome=80.0.3987.106)
            For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/stale_element_reference.html
            Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
            System info: host: 'SLB-2XQZ7S2', ip: '100.97.130.212', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_201'
            Driver info: org.openqa.selenium.chrome.ChromeDriver
            Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 80.0.3987.106, chrome: {chromedriverVersion: 79.0.3945.36 (3582db32b3389…, userDataDir: C:\Users\DGOVIN~1\AppData\L…}, goog:chromeOptions: {debuggerAddress: localhost:58091}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
            Session ID: acb36c28ad8d1aff8c682159f71e24bf

            [ERROR] runScenario(StepDefinition.RunnerIT) Time elapsed: 242.579 s <<< FAILURE!
            org.openqa.selenium.StaleElementReferenceException:
            stale element reference: element is not attached to the page document
            (Session info: chrome=80.0.3987.106)
            For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/stale_element_reference.html
            Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
            System info: host: 'SLB-2XQZ7S2', ip: '100.97.130.212', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_201'
            Driver info: org.openqa.selenium.chrome.ChromeDriver
            Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 80.0.3987.106, chrome: {chromedriverVersion: 79.0.3945.36 (3582db32b3389…, userDataDir: C:\Users\DGOVIN~1\AppData\L…}, goog:chromeOptions: {debuggerAddress: localhost:58092}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
            Session ID: 5e21e6a53c9a7f52adddc3573e387a0d

            [INFO]
            [INFO] Results:
            [INFO]
            [ERROR] Failures:
            [ERROR] StepDefinition.RunnerIT.runScenario(StepDefinition.RunnerIT)
            [ERROR] Run 1: RunnerIT.runScenario » StaleElementReference stale element reference: element …
            [ERROR] Run 2: RunnerIT.runScenario » StaleElementReference stale element reference: element …
            [INFO]
            [INFO]
            [ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
            [INFO]
            [ERROR] There are test failures.

        1. Hi Mounish,

          I added my stacktrace.

          at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:249)
          at PageFactoryElements.Dashboard.navigateTojobmanagement(Dashboard.java:85)
          at StepDefinition.CreateOpsActivitySD.userNavigatedDeBrieffromOpsActivityDashboardAndChooseProfile(CreateOpsActivitySD.java:204)
          at ?.the user navigated to DeBrief page from Operation activity dashboard and choose the profile based on “Bergen WL”(Regression/Feature/Operation management/19_812910_Debrief.feature:8)

          End Date & Time of Execution – Wed Feb 26 15:32:13 IST 2020
          Total no of Test case passed Percentage – 0
          [ERROR] Tests run: 2, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 203.313 s <<< FAILURE! – in TestSuite
          [ERROR] runScenario(StepDefinition.TestRunner) Time elapsed: 101.189 s <<< FAILURE!
          org.openqa.selenium.StaleElementReferenceException:
          stale element reference: element is not attached to the page document
          (Session info: chrome=80.0.3987.106)
          For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/stale_element_reference.html
          Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
          System info: host: 'SLB-2XQZ7S2', ip: '100.97.130.212', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_201'
          Driver info: org.openqa.selenium.chrome.ChromeDriver
          Capabilities {acceptInsecureCerts: true, browserName: chrome, browserVersion: 80.0.3987.106, chrome: {chromedriverVersion: 79.0.3945.36 (3582db32b3389…, userDataDir: C:\Users\DGOVIN~1\AppData\L…}, goog:chromeOptions: {debuggerAddress: localhost:62342}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
          Session ID: e337143126bdc683ea6fe784549be9be

          [ERROR] runScenario(StepDefinition.TestRunner) Time elapsed: 197.831 s <<< FAILURE!
          org.openqa.selenium.NoSuchSessionException:
          Session ID is null. Using WebDriver after calling quit()?
          Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
          System info: host: 'SLB-2XQZ7S2', ip: '100.97.130.212', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_201'
          Driver info: driver.version: RemoteWebDriver

          1. Check this line in the stacktrace – “Session ID is null. Using WebDriver after calling quit()?” Is the driver being closed by another thread, is the driver static?

  13. Hi,

    I am getting below error while adding below dataproviderthreadcount property in POM.xml.

    Project build error: Non-parseable POM C:\testngsharedwebdriver\pom.xml: TEXT must be immediately followed by END_TAG and not START_TAG (position: START_TAG seen …\r\n …
    @20:15)

    Here is the POM.xml conetnt

    UTF-8
    UTF-8
    1.8
    1.8

    4.4.0
    3.141.59

    dataproviderthreadcount
    4

  14. How to access the Selenium Webdriver to add waits (explicit, fluent) and navigate to driver object in stepdefinations to perform actions.

  15. Is it possible to use this method to run entire suites in parallel per thread? In my setup, I have a separate mobile device per thread. The above distributes the features across the devices but if I want to run the entire suite per thread/device, is that possible using the above method? Distributing the feature files is fine if all the devices are the same, but I’m looking to get a full run on a number of different devices. I know this would probably mess up the reporting. I thought changing the failsafe parallel property to suites rather than methods would suffice but unfortunately, it just runs the entire suite on the first connected device.

    1. What could work is using the ‘classes’ setting to run in parallel mode and creating multiple runners equal to the number of devices. Each runner will need to have a BeforeClass method in which the driver specific for that device is created and stored in the DriverFactory class.
      For a JUnit (http://grasshopper.tech/464/) runner it is matter of setting ‘classes‘ in the configuration of failsafe. For TestNG (http://grasshopper.tech/466/) runner DO NOT override scenarios() method just extend the normal AbstractTestNGCucumberTests. Set the setting ‘classes‘ in the configuration of failsafe. Check the POM’s in the respective articles.
      I think this might work. Cucumber might complain about same feature files for runners, not sure though. Only way out is to copy for each device and store in separate folders. U can automate the copying stuff in some earlier maven phase.
      Regarding reporting, have a look at cluecumber reporting. Create separate json files from each runner and this plugin will consolidate everything for u. — https://github.com/trivago/cluecumber-report-plugin.

      1. Thanks for the response. I was thinking of something similar. Doesn’t look like Cucumber supports full runs in parallel, which is understandable. I’m currently writing a script to get the capabilities of all attached devices and then maybe run a maven command for each one, passing the capabilities as a property to my Junit BeforeClass, kicking off a separate run for all. That would create a number of different reports, but that’s probably a good thing, wanting to keep each device separate.

        1. Yes I have done this and seems like the only solution. Also if you go with JUnit, you don’t really need to create seperate runners for each device. You can send the device capabilities as system properties. You can also override report paths. With TestNG, I’m yet to figure out reporting, so for now I have created seperate runners for each device and then running “tests” as parallel. This runs good for multiple feature files as well. And this will create seperate reports. Now the only thing to check is how to merge these device specific reports and create a single report categorizing according to device for easy readability. If this is not possible or too much of work, Extent reports is always there that supports parallel execution.

  16. Hi,

    I tried following the above steps for TestNG and I am getting the following error while running the runner class from eclipse:

    java.lang.NoSuchMethodError: org.testng.TestRunner.addListener(Ljava/lang/Object;)V
    at org.testng.remote.support.RemoteTestNG6_9_10$1.newTestRunner(RemoteTestNG6_9_10.java:32)
    at org.testng.remote.support.RemoteTestNG6_9_10$DelegatingTestRunnerFactory.newTestRunner(RemoteTestNG6_9_10.java:61)
    Please help.

    1. Are u using the POM mentioned above? What is the version of testNG? Seems like 6.9.10. Can u try with 6.14.3

Leave a Reply

Your email address will not be published. Required fields are marked *