javaspringseleniumcucumbertestng

Cant run Cucumber tests in parallel using TestNG and SpringBootTest


I'm trying to run 2 Cucumber tests in parallel using TestNG and SpringBootTest but when my tests execute the following happens

I'm not sure why one test stops executing, any help would be welcome.

Test Runner

@CucumberOptions(
        features = {
                "src/test/resources/feature/"
        },
        plugin = {
                "pretty",
                "html:target/cucumber/report-html",
                "json:target/cucumber/report.json",
                "junit:target/cucumber/junit_report.xml",
                "timeline:target/cucumber/timeline"
        })
public class ParallelRunner extends AbstractTestNGCucumberTests {

    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }

}

DriverManager Class

@Component
public class DriverManager {

    private WebDriver webDriver;
    private Wait<WebDriver> webDriverWait;
    private static ThreadLocal<WebDriver> driverThreadLocal = new ThreadLocal<>();
    private static ThreadLocal<Wait<WebDriver>> driverWaitThreadLocal = new ThreadLocal<>();

    @Autowired
    private ApplicationProperties applicationProperties;

    public void driverManager() {
        if (getDriver() == null) {
            setLocalWebDriver();
        }
    }

    public void setLocalWebDriver() {
        switch (applicationProperties.getBrowser()) {
...
            case ("firefox"):
                System.setProperty("webdriver.gecko.driver", System.getProperty("user.dir") + "/src/test/resources/geckodriver");
                FirefoxOptions firefoxOptions = new FirefoxOptions();
//                firefoxOptions.setHeadless(true);
                firefoxOptions.setCapability("marionette", true);

                webDriver = new FirefoxDriver(firefoxOptions);
                break;
       ...
            default:
                throw new NoSuchElementException("Failed to create an instance of WebDriver for: " + applicationProperties.getBrowser());
        }
        driverThreadLocal.set(webDriver);
        webDriverWait = new WebDriverWait(webDriver, 10, 500);
        driverWaitThreadLocal.set(webDriverWait);
        try {
            Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
        }catch(Exception ex){
            System.out.println("ex.getMessage() = " + ex.getMessage());
        }
    }

    ...

Solution

  • Change the PageObject annotation and add @Scope("prototype") Refer

    @Retention(RUNTIME)
    @Target({ElementType.FIELD, ElementType.TYPE})
    @PageFactoryFinder(FindBy.FindByBuilder.class)
    @Lazy
    @Component
    @Scope("prototype")
    public @interface PageObject {
    }
    

    Now for each scenario you should get the new instance of page object .

    Also I may prefer to have some changes in DriverManager e.g.

    driverThreadLocal.set(new FirefoxDriver(firefoxOptions));
    driverWaitThreadLocal.set(new WebDriverWait(driverThreadLocal.get(), 10, 500));
    

    You can remove this logic of cleaning the drivers

    try { Runtime.getRuntime().addShutdownHook(CLOSE_THREAD); }catch(Exception ex){ System.out.println("ex.getMessage() = " + ex.getMessage()); }

    Move Driver.Quit to Hooks.java https://github.com/cmccarthyIrl/spring-cucumber-test-harness/blob/testng/wikipedia/src/test/java/com/cmccarthy/step/Hooks.java

      @After
        public void afterScenario(Scenario scenario) {
            hookUtil.endOfTest(StringUtils.capitalize(scenario.getStatus().toString()));
            driverManager.getDriver().quit();
        }