Are you looking for class-level DataProvider?
In order to parametrize the test class, use @Factory
+ @DataProvider
in the next way:
import org.testng.annotations.DataProvider
import org.testng.annotations.Factory
import org.testng.annotations.Test
class MyTestClass {
String arg1;
String arg2;
@Factory(dataProvider = "provideClassArgs")
public MyTestClass(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
@DataProvider
public static Object[][] provideClassArgs() {
return new Object[]{
{"arg1-value1", "arg2-value1"},
{"arg1-value2", "arg2-value2"}
};
}
@Test
public void test1() {
System.out.println("Do test1 with: " + arg1 + ", " + arg2);
}
@Test
public void test2() {
System.out.println("Do test2 with: " + arg1 + ", " + arg2);
}
@Test
public void test3() {
System.out.println("Do test3 with: " + arg1 + ", " + arg2);
}
}
with the next textng.xml
NOTE: group-by-instances="true"
should be defined
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Test Suite" group-by-instances="true">
<test name="Test">
<classes>
<class name="samples.MyTestClass"/>
</classes>
</test>
</suite>
you will get:
Do test1 with: arg1-value2, arg2-value2
Do test2 with: arg1-value2, arg2-value2
Do test3 with: arg1-value2, arg2-value2
Do test1 with: arg1-value1, arg2-value1
Do test2 with: arg1-value1, arg2-value1
Do test3 with: arg1-value1, arg2-value1
Class Execution Order
By default, DataProvider items will launch classes in random order.
The easiest way to make the order fixed: is override toString()
method for test-class.
For this example:
@Override
public String toString() {
return "MyTestClass";
}
tests will be sorted alphabetically based on DataProvider args, converted to a string. This won't be the natural order like in DataProvider, but at least not random.
See more:
Use Factory with DataProvider for multiple classes
NOTE: the request is to run all the classes per args line, and then the same classes per next arg line, etc.
Create the parent class for all test classes.
- It should define all the required arguments
- It should have a constructor for all the arguments
- It should override
toString()
method, the result to be reflected by all the args. This is valuable for the execution order.
public class MyClassParent {
String arg1;
String arg2;
public MyClassParent(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
@Override
public String toString() {
arg1.toString() + arg2.toString();
}
}
Implement test classes, like:
- Extend from
MyClassParent
- Create the same constructor
public class MyTestClass1 extends MyClassParent {
public MyTestClass1(String arg1, String arg2) {
super(arg1, arg2);
}
@Test
public void test1() {
System.out.println("MyTestClass1: Do test1 with: " + arg1 + ", " + arg2);
}
}
- Implement Factory with DataProvider.
Factory with DataProvider moved to separate class and produces test class objects array.
- For applying the correct ordering
IMethodInterceptor
TestNG Listener interface was implemented.
- And applied for the class with
@Listeners(MyFactory)
.
intercept
method overridden and sorting applied here.
- Custom Comparator implemented for sorting, which compare 2
MyClassParent
based on it's toString()
results.
So while toString()
depends on the MyClassParent
args, all the classes for the same args will be in the same group.
import org.testng.IMethodInstance
import org.testng.IMethodInterceptor
import org.testng.ITestContext
import org.testng.annotations.DataProvider
import org.testng.annotations.Factory
import org.testng.annotations.Listeners
@Listeners(MyFactory)
public class MyFactory implements IMethodInterceptor {
@Factory(dataProvider = "provideClassArgs")
public Object[] generateTests(String arg1, String arg2) {
return new Object[] {
new MyTestClass1(arg1, arg2),
new MyTestClass2(arg1, arg2),
new MyTestClass3(arg1, arg2),
new MyTestClass4(arg1, arg2),
new MyTestClass5(arg1, arg2)
};
}
@DataProvider
public static Object[][] provideClassArgs() {
return new Object[]{
{"arg1-value1", "arg2-value1"},
{"arg1-value2", "arg2-value2"},
{"arg1-value3", "arg2-value2"}
};
}
@Override
List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
// applying sorting is essential to change the tests order
methods.sort(new MyTestClassComparator());
return methods;
}
// internal class added, assumed it should compare only methods from MainImpClass
// here compareTo delegated to getA() results
class MyTestClassComparator implements Comparator<IMethodInstance> {
@Override
int compare(IMethodInstance o1, IMethodInstance o2) {
return ((MyClassParent)o1.getInstance()).toString().compareTo(((MyClassParent)o2.getInstance()).toString());
}
}
}
4 TestNG xml:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Test Suite" group-by-instances="true">
<test name="Test">
<classes>
<class name="samples.MyFactory"/>
</classes>
</test>
</suite>
The final output:
MyTestClass1: Do test1 with: arg1-value1, arg2-value1
MyTestClass2: Do test2 with: arg1-value1, arg2-value1
MyTestClass3: Do test3 with: arg1-value1, arg2-value1
MyTestClass4: Do test4 with: arg1-value1, arg2-value1
MyTestClass5: Do test5 with: arg1-value1, arg2-value1
MyTestClass1: Do test1 with: arg1-value2, arg2-value2
MyTestClass2: Do test2 with: arg1-value2, arg2-value2
MyTestClass3: Do test3 with: arg1-value2, arg2-value2
MyTestClass4: Do test4 with: arg1-value2, arg2-value2
MyTestClass5: Do test5 with: arg1-value2, arg2-value2
MyTestClass1: Do test1 with: arg1-value3, arg2-value2
MyTestClass2: Do test2 with: arg1-value3, arg2-value2
MyTestClass3: Do test3 with: arg1-value3, arg2-value2
MyTestClass4: Do test4 with: arg1-value3, arg2-value2
MyTestClass5: Do test5 with: arg1-value3, arg2-value2