Reputation: 23
I want to run test methods which are dependent and use ITestContext, to run in parallel with different parameters using Data Provider in TestNg. I am trying to call the test class pragmatically.
The code looks like this:
package com.ExploringTestNg;
import java.util.Random;
import org.testng.ITestContext;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ParallelMethodTest {
@Test(dataProvider = "dataprovider")
public void testclass1(ITestContext context,String deviceId) {
long id = Thread.currentThread().getId();
System.out.println("TestClass1 is being called and context is being setup");
System.out.print("The thread id is "+id);
System.out.println("device id is "+deviceId);
context.setAttribute("deviceId",deviceId);
}
@Test(dependsOnMethods = {"testclass1"})
public void testclass2(ITestContext context) {
long id = Thread.currentThread().getId();
System.out.println("TestClass2 is being called and context is being retrieved "+(String)context.getAttribute("deviceId"));
System.out.println("The thread id is "+id+"\n");
}
@Test(dependsOnMethods = {"testclass2"})
public void testclass3(ITestContext context) {
long id = Thread.currentThread().getId();
System.out.println("TestClass3 is being called and context is being retrieved "+(String)context.getAttribute("deviceId"));
System.out.println("The thread id is "+id);
}
@DataProvider(name = "dataprovider",parallel = true)
public Object[][] getDataFromDataprovider(){
return new Object[][]
{
{"1001"},
{"1002"},
{"1003"}
};
}
}
package com.ExploringTestNg;
import java.util.ArrayList;
import java.util.List;
import org.testng.TestNG;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;
public class DynamicXMLSetuo {
public static void main(String[] args) {
XmlSuite suite = new XmlSuite();
suite.setName("TempSuite1");
XmlTest test = new XmlTest(suite);
test.setName("Functional usecase 1");
List<XmlClass> classes = new ArrayList<XmlClass>();
classes.add(new XmlClass("com.ExploringTestNg.ParallelMethodTest"));
test.setXmlClasses(classes);
List<XmlSuite> suites = new ArrayList<XmlSuite>();
suites.add(suite);
TestNG tng = new TestNG();
tng.setXmlSuites(suites);
tng.setThreadCount(5);
tng.setParallel(XmlSuite.ParallelMode.METHODS);
tng.run();
}
}
My functionality is to call the test class multiple times with different parameters and the classes being called should run parallelly
Upvotes: 2
Views: 777
Reputation: 4935
The issue with this is that the testclass1
would be invoked three times, but the testclass2
and testclass3
would be invoked only once because, the execution of those methods does not depend on the number of times testclass1
is executed. It only depends on whether testclass1
passed or not. To solve the issue, you need to use @Factory
public class ParallelMethodTest {
private final String deviceId;
ParallelMethodTest(String id) {
this.deviceId = id;
}
@DataProvider(parallel = true)
public static Object[][] dataProvider() {
return new Object[][] { { "1001" }, { "1002" }, { "1003" } };
}
@Factory(dataProvider = "dataProvider")
public Object[] createInstances(String id) {
// The factory method uses the dataProvider to initialize
// multiple instances of the test class.
return new Object[] { new ParallelMethodTest(id) };
}
@Test
public void testclass1() {
long id = Thread.currentThread().getId();
System.out.println("TestClass1 is being called and context is being setup");
System.out.print("The thread id is " + id);
System.out.println("device id is " + deviceId);
}
@Test(dependsOnMethods = { "testclass1" })
public void testclass2() {
long id = Thread.currentThread().getId();
System.out.println("TestClass2 is being called and context is being retrieved " + deviceId);
System.out.println("The thread id is " + id + "\n");
}
@Test(dependsOnMethods = { "testclass2" })
public void testclass3() {
long id = Thread.currentThread().getId();
System.out.println("TestClass3 is being called and context is being retrieved " + deviceId);
System.out.println("The thread id is " + id);
}
}
With this, there is no need for storing the deviceId
in test context as the corresponding deviceId
would be available in the class itself.
UPDATE : To run in parallel, you need to do one more thing inside DynamicXMLSetuo
.
suite.setParallel(XmlSuite.ParallelMode.METHODS);
By adding ParallelMode.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.
Upvotes: 1