Hari
Hari

Reputation: 51

Parallel method execution in testng executes only the last method invoked from the class

I have a testing suite file with a class having 3 methods. In the suite level I gave parallel="methods" thread-count="3" so that 3 threads open in parallel for each method in the class.

When executed the suite, 3 threads (browser's) are opened launching the URL but only the 3rd thread/browser is executed as per the steps in the method. For the 1st 2 threads/ browser's no actions where performed.

Tried a lot to find answers for this issue but couldn't find the solution. Below is the code i use and Please correct me if i miss something.

BaseClass:

public class BaseClass {

    public WebDriver driver;
    public WebDriverWait wait;

    @BeforeMethod()
    public void configure() {
        System.setProperty("webdriver.chrome.driver","C:\\SeleniumDrivers\\chromedriver.exe");
          driver=new ChromeDriver();
          driver.get("https://www.google.com");
          driver.manage().window().maximize();
          driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);          
    }

    @AfterMethod()
    public void tearDown() {
        driver.quit();
    }

}

Class with TestMethods

  public class NewTest extends BaseClass{
  @Test()
  public void method1() {
      driver.findElement(By.name("q")).sendKeys("parallel");
      driver.findElement(By.name("q")).sendKeys(Keys.ENTER);
  }

  @Test()
  public void method2() {
      driver.findElement(By.name("q")).sendKeys("methods");  
      driver.findElement(By.name("q")).sendKeys(Keys.ENTER);

  }

  @Test()
  public void method3() {
      driver.findElement(By.name("q")).sendKeys("testng");
      driver.findElement(By.name("q")).sendKeys(Keys.ENTER);
  }
}

Suite File

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="methods">
  <test thread-count="5" name="Test">
    <classes>
      <class name="website.NewTest"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

Expected Result: 3 browsers to open in parallel. 1st browser should search for "parallel". 2nd browser should search for "methods". 3rd browser should search for "automation".

Actual Result: 3 browsers open in parallel but 2 browsers which are opened first does perform actions as per the method and the last browser opened searches for the word "parallelmethodtestng" and closes. First 2 browsers opened does not close neither maximize as per the code.

===============================================
Suite
Total tests run: 3, Failures: 2, Skips: 0
===============================================

Hope this helps.

Upvotes: 2

Views: 1656

Answers (4)

Muzzamil
Muzzamil

Reputation: 2881

This can be happened as thread-count is not on correct place. As per TestNG documentation thread-countshould be in suite tag. Please use it as mentioned below.

<suite name="My suite" parallel="methods" thread-count="5">

Check testng documentation here:

http://testng.org/doc/documentation-main.html#parallel-running

Upvotes: 1

Eleb
Eleb

Reputation: 11

If u would like to use only TestNG without any extension you need to handle webdriver via ThreadLocal

private final ThreadLocal<WebDriver> driver = new ThreadLocal<>();

Drivers should be create via synchronized methods.

public synchronized WebDriver createDriver() {
        return new ChromeDriver(options.getOptions());
}
@BeforeMethod(alwaysRun = true)
public void setupDriver(String browser) {
    driver.set(CcreateDriver());
}
public synchronized WebDriver getDriver() {
        return driver.get();
}

You need also remeber to use thread safe maps, lists etc like concurentHashMap etc. It is also applied for Selenium Grid. So ThreadLocal should be also applied to RemoteWebDriver as its also not thread safe.

Upvotes: 0

user861594
user861594

Reputation: 5908

I would suggest to use qaf TestNG extension, which takes care of driver management, resource management and many more for web, mobile and web-services functional test automation. With qaf your test class may look like below:

 public class NewTest extends WebDriverTestCase{
  @Test()
  public void method1() {
      getDriver().get("https://www.google.com");
      getDriver().findElement(By.name("q")).sendKeys("parallel");
      getDriver().findElement(By.name("q")).sendKeys(Keys.ENTER);
  }

  @Test()
  public void method2() {
      getDriver().get("https://www.google.com");
      //another improved way
      WebElement ele = getDriver().findElement(By.name("q"));
      ele.sendKeys("methods");  
      ele.sendKeys.submit();

  }

  @Test()
  public void method3() {
      getDriver().get("https://www.google.com");
      //another way with qaf
      WebElement ele = $("name=q");
      ele.sendKeys("testng");  
      ele.sendKeys.submit();
  }
}

Further more you can make test data-driven using in-built data providers.

Upvotes: 0

Jens Dibbern
Jens Dibbern

Reputation: 1454

WebDriver is not thread safe. I may cite the Selenium FAQ

Q: Is WebDriver thread-safe?
A: WebDriver is not thread-safe. Having said that, if you can serialise access to the underlying driver instance, you can share a reference in more than one thread. This is not advisable. You /can/ on the other hand instantiate one WebDriver instance for each thread.

It is irrelevant if your solution is used in huge or small projects. If you want to scale your solution you can always use a Selenium grid for parallel execution. Local WebDriver objects will not be your problem. Forking memory eating Chrome instances will be your problem.

Upvotes: 0

Related Questions