title: Running Parallel Tests using Selenium WebDriver, Selenium Grid and testNG
body: <p>This is my very first post here in SO; I am a newbie Selenium User with beginner skill in Java.</p>
  
  <p>To give you a background of our work; we are using <strong>Page Object Model</strong>. All of our tests uses a single <strong>DataProvider</strong> method that fetches its data from an ".xlsx" file based on the test case name that calls/uses the DataProvider.</p>
  
  <p>We are unsure however if we have declared our <strong>ThreadLocal</strong> the way it should be.  And also, we are not sure if the declaration of our <strong>getDriver()</strong> method is correct.  Another issue is that we are unsure if we should be using <strong><em>"@BeforeTest"/"@AfterTest"</em></strong> or <strong><em>"@BeforeClass"/"@AfterClass"</em></strong> on our <strong>setup</strong> and <strong>tearDown</strong> methods.</p>
  
  <p>The following problems are being encountered:</p>
  
  <ol>
  <li>One test fails, the succeeding test also fails.</li>
  <li>There are times when the test data being fetched is inaccurate (more column data thrown than expected).</li>
  </ol>
  
  <p><br>
  <strong><em>Here is our CONFIGTESTBASE class:</em></strong></p>
  
  <pre><code>public class ConfigTestBase {
  
      private static ThreadLocal&lt;RemoteWebDriver&gt; threadedDriver = null;
      private static XSSFSheet ExcelWSheet;
      private static XSSFWorkbook ExcelWBook;
      private static XSSFCell Cell;
      private static XSSFRow Row;
      private static final String Path_TestData = GlobalConstants.testDataFilePath;
      private static final String File_TestData = GlobalConstants.testDataFileName;
  
      @Parameters({"objectMapperFile"})
      @BeforeSuite
      public void setupSuite(String objectMapperFile) throws Exception {
          GlobalConstants.objectMapperDefPath = new File(objectMapperFile).getAbsolutePath();
          new Common().OverrideSSLHandshakeException();
      }
  
      @Parameters({"browserName"})
      @BeforeClass
      public void setup(String browserName) throws Exception {
  
          threadedDriver = new ThreadLocal&lt;&gt;();
  
          DesiredCapabilities capabilities = new DesiredCapabilities();
  
          if (browserName.toLowerCase().contains("firefox")) {
              capabilities = DesiredCapabilities.firefox();
              capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
              capabilities.setBrowserName("firefox");
              capabilities.setPlatform(Platform.WINDOWS);
          }
  
          if (browserName.toLowerCase().contains("ie")) {
              System.setProperty("webdriver.ie.driver","C:\\selenium\\IEDriverServer.exe");
              capabilities = DesiredCapabilities.internetExplorer();
              capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
              capabilities.setCapability(InternetExplorerDriver.FORCE_CREATE_PROCESS, false);
              capabilities.setBrowserName("internet explorer");
              capabilities.setPlatform(Platform.WINDOWS);
          }
  
          if (browserName.toLowerCase().contains("chrome")) {
              System.setProperty("webdriver.chrome.driver","C:\\selenium\\chromedriver.exe");
              capabilities = DesiredCapabilities.chrome();
              capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
              capabilities.setBrowserName("chrome");
              capabilities.setPlatform(Platform.WINDOWS);
          }
  
          if (browserName.toLowerCase().contains("safari")) {
              SafariOptions options = new SafariOptions();
              options.setUseCleanSession(true);
              capabilities = DesiredCapabilities.safari();
              capabilities.setCapability(SafariOptions.CAPABILITY, options);
              capabilities.setBrowserName("safari");
              capabilities.setPlatform(Platform.WINDOWS);
          }
  
          threadedDriver.set(new RemoteWebDriver(new URL(GlobalConstants.GRIDHUB), capabilities));
  
      }
  
      protected static RemoteWebDriver getDriver(){
          RemoteWebDriver driver = null;
  
          try {
              driver = threadedDriver.get();
          } catch (Exception e) {
              e.printStackTrace();
          }
          return driver;
      }
  
      @AfterClass
      public void tearDown() throws Exception {
          getDriver().quit();
      }
  
      //This method is to set the File path and to open the Excel file, Pass Excel Path and Sheetname as Arguments to this method
      public void setExcelFile(String Path,String SheetName) throws Exception {
          try {
              // Open the Excel file
              FileInputStream ExcelFile = new FileInputStream(Path);
  
              // Access the required test data sheet
              ExcelWBook = new XSSFWorkbook(ExcelFile);
              ExcelWSheet = ExcelWBook.getSheet(SheetName);
          } catch (Exception e) {
              throw (e);
          }
      }
  
      //This method is to read the test data from the Excel cell, in this we are passing parameters as Row num and Col num
      @SuppressWarnings("static-access")
      public String getCellData(int RowNum, int ColNum) throws Exception{
          try{
              Cell = null;
              Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
              Cell.setCellType(Cell.CELL_TYPE_STRING);
              return Cell.getStringCellValue();
          } catch (Exception e) {
              return "";
          }
      }
  
      //This method is to write in the Excel cell, Row num and Col num are the parameters
      @SuppressWarnings("static-access")
      public void setCellData(String textValue,  int RowNum, int ColNum) throws Exception    {
          try{
              Row  = ExcelWSheet.getRow(RowNum);
              Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL);
              if (Cell == null) {
                  Cell = Row.createCell(ColNum);
                  Cell.setCellValue(textValue);
              } else {
                  Cell.setCellValue(textValue);
              }
  
              // Constant variables Test Data path and Test Data file name
              FileOutputStream fileOut = new FileOutputStream(Path_TestData + File_TestData);
              ExcelWBook.write(fileOut);
              fileOut.flush();
              fileOut.close();
          } catch (Exception e) {
              throw (e);
          }
      }
  
      @DataProvider(name="getDataFromFile")
      public Object[][] getDataFromFile(Method testMethod, ITestContext context) throws Exception {
  
          String[][] tabArray;
          int intCounter;
          int intRowCount = 0;
          int intRowCounter = 0;
          int intColCount = 0;
          int intColCounter;
          int intColDataCount = 0;
          int intColDataCounter = 0;
          String temp;
  
          String testName = testMethod.getName();
          String banner = context.getCurrentXmlTest().getParameter("banner");
          setExcelFile(Path_TestData + File_TestData, banner);
  
          //get number of data to be returned
          for(intCounter=0;intCounter&lt;ExcelWSheet.getLastRowNum()+1;intCounter++){
              if(getCellData(intCounter, 1).equals(testName)) {
                  if (intColCount == 0) {
                      intColCount = ExcelWSheet.getRow(intCounter).getLastCellNum() - 2;
                  }
                  intRowCount++;
              }
          }
  
          if(intRowCount == 0){
              System.out.println("\n*** Data for '" + testName + "' was not found.");
              throw new AssertionError("Data for '" + testName + "' was not found.");
          }
  
          for(intCounter=0;intCounter&lt;ExcelWSheet.getLastRowNum()+1;intCounter++){
              if(getCellData(intCounter, 1).equals(testName)) {
                  for(intColCounter=2;intColCounter&lt;intColCount+2;intColCounter++) {
                      temp = getCellData(intCounter,intColCounter);
                      if(temp != null &amp;&amp; !temp.isEmpty()){
                          intColDataCount++;
                      }
                  }
                  //to exit FOR loop
                  intCounter = ExcelWSheet.getLastRowNum()+1;
              }
          }
  
          //set data array dimension
          tabArray = new String[intRowCount][intColDataCount];
  
          for(intCounter=0;intCounter&lt;ExcelWSheet.getLastRowNum()+1;intCounter++){
              if(getCellData(intCounter, 1).equals(testName)) {
                  intRowCounter++;
                  for(intColCounter=2;intColCounter&lt;intColCount+2;intColCounter++) {
                      temp = getCellData(intCounter,intColCounter);
                      if(temp != null &amp;&amp; !temp.isEmpty()){
                          tabArray[intRowCounter-1][intColDataCounter] = getCellData(intCounter,intColCounter);
                          intColDataCounter++;
                      }
                  }
              }
          }
  
          return tabArray;
  
      }
  
  }
  </code></pre>
  
  <p><br>
  <strong><em>Here is a sample test class that we have; extends CONFIGTESTBASE class... one class per test:</em></strong></p>
  
  <pre><code>public class Google6 extends ConfigTestBase {
  
      private Generic generic = null;
      private HomePage homePage = null;
  
      @BeforeMethod
      public void MethodInit(ITestResult result) throws Exception {
          generic = new Generic(getDriver());
          homePage = new HomePage(getDriver());
      }
  
      @Test(dataProvider="getDataFromFile")
      public void Google6(String execute, String url, String searchString) throws Exception {
  
          if(execute.toUpperCase().equals("YES")) {
  
              //navigate to application page
              generic.navigateToURL(url);
  
              //search
              homePage.search(searchString);
  
          } else {
              generic.log("Execute variable &lt;&gt; 'YES'. Skipping execution...");
              throw new SkipException("Execute variable &lt;&gt; 'YES'. Skipping execution...");
          }
  
      }
  }
  </code></pre>
  
  <p><br>
  <strong><em>And here is our suite file; 'banner' parameter is used for finding specific sheet on ".xlsx" file:</em></strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"&gt;
  
  &lt;suite name="Full Test Suite - Firefox" parallel="classes" thread-count="5" verbose="1"&gt;
      &lt;parameter name="objectMapperFile" value="mom.objectdef.properties" /&gt;
  
      &lt;test name="Regression - Firefox"&gt;
          &lt;parameter name="browserName" value="firefox" /&gt;
          &lt;parameter name="banner" value="SAMPLE" /&gt;
          &lt;classes&gt;
              &lt;class name="com.company.automation.web.app.testsuites.Google1" /&gt;
              &lt;class name="com.company.automation.web.app.testsuites.Google2" /&gt;
              &lt;class name="com.company.automation.web.app.testsuites.Google3" /&gt;
              &lt;class name="com.company.automation.web.app.testsuites.Google4" /&gt;
              &lt;class name="com.company.automation.web.app.testsuites.Google5" /&gt;
              &lt;class name="com.company.automation.web.app.testsuites.Google6" /&gt;
          &lt;/classes&gt;
      &lt;/test&gt;
  
  &lt;/suite&gt;
  </code></pre>
  
  <p><br>
  Any suggestions on how we could make it work?</p>