Parallel Run with TestNG

Modern computers can have 2 to 4 processor cores (or even more),and running one single task at one time would only utilize a fraction of the computer’s CPU. To take advantage of multiple processors, we shall run our tests across multiple browsers at the same time, or go even further and distribute all your tests across all available browsers.

Here is a simple example of running the same test cases in Firefox and Chrome in parallel, using java, selenium webdriver and testNG.

First, let’s define a simple test case: Launch the browser, load www.automeditator.com and then search for ‘jenkins’:

//import part is skipped

public class AutomediatorSearchTest {
private WebDriver driver;
String browser ;
String methodName =””;
final String URL = “http://www.automeditator.com/”;

@Parameters({ “browser” })
@BeforeMethod
public void init(Method method, String browser) {
//DriverFactory is a class to create thread-safe WebDriver instance for each thread.
// The source code is attached at the end of this article
DriverFactory.getInstance().setBrowser(browser);
driver = DriverFactory.getInstance().getDriver();
driver.get(URL);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
methodName = method.getName();
System.out.println(“test method:” + method.getName() + ” started.” );
}

@Test
public void testSearch() {
WebElement searchField = driver.findElement(By.className(“search-field”));
searchField.click();
searchField.sendKeys(“jenkins”);
searchField.sendKeys(Keys.ENTER);
assertTrue(driver.getTitle().contains(“Search Results”));
}

@AfterMethod
public void tearDown(ITestResult result) throws Exception{
DriverFactory.getInstance().removeDriver();
}
}

We want to run the case in both firefox and chrome in parallel, and we want to use different threads for different browsers, so here comes the testng.xml:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE suite SYSTEM “http://testng.org/testng-1.0.dtd” >
<suite name=”Test Search In different browsers” parallel=”tests” verbose=”1″ thread-count=”2″>
<test name=”Test in Firefox”>
<parameter name=”browser” value=”firefox”/>
<classes>
<class name=”com.buxie.selenium.testNGfun.AutomediatorSearchTest”/>
</classes>
</test>
<test name=”Test in Chrome”>
<parameter name=”browser” value=”chrome”/>
<classes>
<class name=”com.buxie.selenium.testNGfun.AutomediatorSearchTest”/>
</classes>
</test>
</suite>

When run this code locally, you shall see 2 browsers(Firefox and Chrome) are launched at the same time and the case are running in each in parallel.

Overview of TestNG Parallel Run Options

TestNG provides many options regarding how parallel shall be run, see explanation from TestNG 6.9.10 Documenation:
Parallel tests, classes and methods
The parallel attribute on the tag can take one of following values:

<suite name=”My suite” parallel=”methods” thread-count=”5″>
<suite name=”My suite” parallel=”tests” thread-count=”5″>
<suite name=”My suite” parallel=”classes” thread-count=”5″>
<suite name=”My suite” parallel=”instances” thread-count=”5″>
  • parallel=”methods”: TestNG will run all your test methods in separate threads. Dependent methods will also run in separate threads but they will respect the order that you specified.
  • parallel=”tests”: TestNG will run all the methods in the same tag in the same thread, but each tag will be in a separate thread. This allows you to group all your classes that are not thread safe in the same and guarantee they will all run in the same thread while taking advantage of TestNG using as many threads as possible to run your tests.
  • parallel=”classes”: TestNG will run all the methods in the same class in the same thread, but each class will be run in a separate thread.
  • parallel=”instances”: TestNG will run all the methods in the same instance in the same thread, but two methods on two different instances will be running in different threads.

Additionally, the attribute thread-count allows you to specify how many threads should be allocated for this execution.
Note: the @Test attribute timeOut works in both parallel and non-parallel mode.

You can also specify that a @Test method should be invoked from different threads. You can use the attribute threadPoolSize to achieve this result:

@Test(threadPoolSize = 3, invocationCount = 10, timeOut = 10000)
public void testServer() {

In this example, the function testServer will be invoked ten times from three different threads. Additionally, a time-out of ten seconds guarantees that none of the threads will block on this thread forever.

The following is DriverFactory.java that is used by above codoe

import io.github.bonigarcia.wdm.ChromeDriverManager;
import io.github.bonigarcia.wdm.InternetExplorerDriverManager;
//all other import statements are skipped
public class DriverFactory
{
private DriverFactory()
{ //Do-nothing
}
private static DriverFactory instance = new DriverFactory();

public static DriverFactory getInstance()
{
return instance;
}

ThreadLocal browser = new ThreadLocal()
{
@Override
protected String initialValue()
{
return getBrowser();
}
};

ThreadLocal driver = new ThreadLocal()
{
@Override
protected WebDriver initialValue()
{
return createWebDriver(browser.get());
}
};

public synchronized void setBrowser(String browser)
{
this.browser.set(browser);
}

public String getBrowser( )
{
return browser.get();
}

public WebDriver getDriver()
{
return driver.get();
}

public void removeDriver()
{
driver.get().quit();
driver.remove();
}

public WebDriver createWebDriver(String browser)
{ WebDriver driver;

if (browser.equalsIgnoreCase(“firefox”))
{
System.setProperty(“webdriver.gecko.driver”,”path to geckodriver.exe”);
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(“marionette”, true);
driver = new FirefoxDriver(capabilities);
}else if (browser.equalsIgnoreCase(“chrome”))
{
ChromeDriverManager.getInstance().setup();
ChromeOptions options = new ChromeOptions();
options.addArguments(“test-type”);
driver = new ChromeDriver(options);
}else if (browser.equalsIgnoreCase(“ie”))
{
InternetExplorerDriverManager.getInstance().setup();
driver = new InternetExplorerDriver();
}else if (browser.equalsIgnoreCase(“edge”))
{
System.setProperty(“webdriver.edge.driver”, “Path to edgeDriver”);
driver = new EdgeDriver();
}else
{
System.out.println(“Unknown browser.”);
return null;
}

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
return driver;
}
}

Leave a Reply

Your email address will not be published. Required fields are marked *