2
votes

I am attempting to run my selenium tests in parallel using TestNG as the runner. The parallel requirement is set in the testng.xml file like so.

<test name="smoke tests" parallel="methods" thread-count="2">

The problem I have is I want to "quit" the browser after each test. I then start a new browser and run the next test. This has worked well for me until I tried to run the tests in parallel. It seems that the methods share threads and if you quit the browser that thread is now gone. TestNG tries to run the next test on the thread that was quit and I get a SessionNotFoundException error.

I have tried parallel="tests" but that doesn't work and the tests are run sequentially instead of in parallel. Is there a way to run each test in a new thread and not reuse threads or am I out of luck?

Here is my @BeforeMethod

private static ThreadLocal<WebDriver> driverForThread;

@BeforeMethod
public static void setUpMethod() {
    log.info("Calling setup before method");

    driverForThread = new ThreadLocal<WebDriver>() {

        @Override
        protected WebDriver initialValue() {
            WebDriver driver = loadWebDriver();
            driver.manage().window().maximize();
            return driver;
        }
    };
}

And my @AfterMethod

@AfterMethod
public static void afterMethod() {
    getDriver().quit();
}

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

Here is a sample test

@Test
public void shouldBeAbleToGetSessionIDTest() {
    login = new LoginPage(getDriver()).get();
    home = login.loginWithoutTelephony(username, password); 
    String sessionID = home.getSessionID();
    Assert.assertNotNull(sessionID);
    log.info("The session text is: " + sessionID);
}
1

1 Answers

1
votes

TestNG has threading built in for methods annotated as@Test. When I ran into this problem, it was because I wasn't threading my WebDriver. Your XML configuration that specifies parallel="methods" is correct.

At the class level, declare two ThreadLocal objects, one with a type WebDriver and the other with type DesiredCapabilities:

ThreadLocal<DesiredCapabilities> capabilities = new ThreadLocal<DesiredCapabilities>();
ThreadLocal<WebDriver> driver = new ThreadLocal<WebDriver>();

Then, in your @BeforeMethod, you'll need to initialize both with new instance of their appropriate types, configure, and start the WebDriver.

capabilities.set(new DesiredCapabilities());
capabilities.get().setBrowserName("Firefox");
driver.set(new RemoteWebDriver(new URL("url of your grid hub"), capabilities.get()));

You'll need to either add a throws declaration to your method or wrap the driver.set() in a try/catch.

At the end of the test, the thread will close and along with it, the DesiredCapabilities and WebDriver. If you want to close these manually, though, you can do so in your @AfterMethod with the appropriate calls (see the ThreadLocal JavaDoc).

This will produce a setup that will start each @Test method in a fresh browser that will be closed at the conclusion of execution.

As an aside, DesiredCapabilities provides a wealth of configuration options for your test environment. Options such as specifying browser, browser version, os platform, and even browser configuration (such as disabling js, etc) are all supported. Using this, the Grid will run the test on a node that supports the given criteria.

Hopefully you'll find this helpful. I ran into the exact problem you describe and this is what solved it for me.