1

Currently, I have a Selenium grid setup, with 1 local hub and 2 local nodes. The hub is capable of distributing the tests to run in parallel and distribute it over to the nodes. I am running the tests in parallel.

The following is the base test

public abstract class BaseTest 
   {    
            String                      testFolder;
            String                      testName;
            protected String            envName;        
            protected Configuration     config;
            protected String            host;
            protected RemoteWebDriver   driver;
            protected String            proxy;
            protected SomeData      someData;
            protected SomeController someController;

            public BaseTest() {
              }

            public BaseTest( String testFolder, String testName) 
            {   
                this.testFolder         = testFolder;
                this.testName           = testName;
                this.envName            = System.getProperty("config");
                this.proxy              = System.getProperty("proxy");
                config = this.envName;
            }

            @BeforeMethod 
            public void startTest(Method testMethod) {
                LOG.info("Starting test: " + testMethod.getName());
                try {
                this.someData       = new SomeData();
                this.driver             = WebDriverSetup.getDriver();
                this.someController = new someController(this.driver, this.someData);
                driver.navigate().to("https://" + this.host);
                } catch (MalformedURLException e) {
                    System.out.println("MalformedURLException");
                }
            }
            @AfterMethod
            public void closeWindow() {
                driver.close();
                driver.quit();
            }
        }

The following is the class to get the RemoteWebDriver:

        public class WebDriverSetup {

            public static RemoteWebDriver getDriver() throws MalformedURLException{

                String SELENIUM_HUB_URL = "http://localhost:4444/wd/hub";
                ThreadLocal<RemoteWebDriver> remoteWebDriver = null;

                DesiredCapabilities capabilities = DesiredCapabilities.firefox();
                capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
                String proxy = System.getProperty("proxy");

                if (proxy != null && !proxy.isEmpty()) {
                    System.out.println("Using proxy: " + proxy);
                    capabilities.setCapability(CapabilityType.PROXY, proxy);
                }

                try {
                    remoteWebDriver = new ThreadLocal<RemoteWebDriver>();
                    remoteWebDriver.set(new RemoteWebDriver(new URL(SELENIUM_HUB_URL),
                            capabilities));
                } catch (MalformedURLException e) {
                    System.out.println("Tackle Issue with RemoteDriverSetup");
                }

                remoteWebDriver.get().manage().window()
                        .setSize(new Dimension(2880, 1524));
                remoteWebDriver.get().manage().timeouts()
                        .pageLoadTimeout(10, TimeUnit.SECONDS);
                remoteWebDriver.get().manage().timeouts()
                        .implicitlyWait(10, TimeUnit.SECONDS);

                return remoteWebDriver.get();
            }
        }

My test suite is like :

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Multiple Tests Suite" verbose="1" parallel="methods">
    <test name="Test1">
        <classes>
            <class name="com.itesteverything.qa.Tests"></class>
        </classes>
    </test>
</suite>

Tests are like :

public class Tests extends BaseTest {

@Parameters({"testName", "env" })
public Tests( @Optional String testName, @Optional String env ) {
    super( null, testName, null, env );
}

@BeforeMethod
public void setup() throws Exception {
    //setSomeData
}   

public void test1() throws Exception {  

use driver from super
use someData from super
use someController is using the driver from super
}

public void test2() throws Exception {  

use driver from super
use someData from super
use someController is using the driver from super
}

While running these tests, I get the following errors

Build info: version: '2.44.0', revision: '76d78cf323ce037c5f92db6c1bba601c2ac43ad8', time: '2014-10-23 13:11:40' Driver info: driver.version: RemoteWebDriver org.openqa.selenium.remote.SessionNotFoundException: Session ID is null. Using WebDriver after calling quit()? Build info: version: '2.44.0', revision: '76d78cf323ce037c5f92db6c1bba601c2ac43ad8', time: '2014-10-23 13:11:40' Driver info: driver.version: RemoteWebDriver at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:572) at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:352) at org.openqa.selenium.remote.RemoteWebDriver.findElementById(RemoteWebDriver.java:393) at org.openqa.selenium.By$ById.findElement(By.java:214) at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:344) at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:59) at com.sun.proxy.$Proxy25.sendKeys(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80) at org.testng.internal.Invoker.invokeMethod(Invoker.java:673) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:842) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1166) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) TEST FAILED: test2 FAILED REASON: Session ID is null. Using WebDriver after calling quit()?

Is it something anyone aware of?

Thanks in advance!

Vivek Singh
  • 3,641
  • 2
  • 22
  • 27

2 Answers2

2

Do not set driver in the base class, do not have driver property at all. The same instance is being overridden by different threadlocal drivers.

Any time you want to run your test, refer to WebDriverSetup.getDriver() in your test method itself and in your after/before methods.

niharika_neo
  • 8,441
  • 1
  • 19
  • 31
  • I tried setting the driver in the @BeforeMethod in the test class itself, that means I have to set the someController and someData in the test too. Given that each driver should have it's own instance of SomeData and SomeController, these two objects should be ThreadSafe too. Sorry I cannot raise another question as it is pertinent to this question only. Would you suggest another class (Let's say ThreadSafeBaseTest) which composes ThreadLocal object and then use it in each TestClass extending ThreadSafeBaseTest or something similar to it? – startedFromTheBottom Dec 16 '14 at 08:12
  • That would depend on what is there in data and controller. Are those things that are specific to each tests? – niharika_neo Dec 16 '14 at 08:37
  • Yes, each test class has a setup method ( using @BeforeMethod ) that uses these objects and assign new values for each test. What would be your suggestion for ThreadLocal approach? – startedFromTheBottom Dec 16 '14 at 16:44
  • @neharika_neo : I have added a new question for test distribution at http://stackoverflow.com/questions/27531619/selenium-grid-driversafe-tests-distribution – startedFromTheBottom Dec 17 '14 at 17:43
1
    @AfterMethod

Is running after each method. And U run's only one setup. So after first method U close and it is closed as shows stack trace.

SkorpEN
  • 2,491
  • 1
  • 22
  • 28
  • what is your recommendation for closing the relevant driver thread after the method is complete? – startedFromTheBottom Dec 16 '14 at 05:31
  • U could use close in @ AfterClass or @ AfterSuite U could also give every test seperate driver. Still it is safer to just use close and quit browser after all tests. In testNG it could be group "clean" or something like that. – SkorpEN Dec 16 '14 at 08:02
  • I already tried closing @AfterSuite too, that would mean it will not close the driver instances until the suite has run completely. I am running some tests right now. Let's see how it works out. Thanks! will keep you posted. – startedFromTheBottom Dec 16 '14 at 08:07