Trying to learn how to use @Factory, but when I execute it in one of two ways, i get either an error or no tests get executed at all. I am invoking the XML file in Eclipse, by right-clicking on it, and selecting "Run As TestNG Suite".
With this XML file, the suite executes, but zero tests are picked up/executed:
<suite name="suite1" verbose="5">
<test name="test1">
<classes>
<class name="qa.tests.MyFactory"/>
</classes>
</test>
</suite>
With this XML file, i get a test failure with an exception:
<suite name="suite1" verbose="5">
<test name="test1">
<packages>
<package name="qa.tests" />
</packages>
</test>
</suite>
Error:
Can't invoke public void qa.tests.MyTest.testSample1(): either make it static or add a no-args constructor to your class
MyFactory.java class:
package qa.tests;
import org.testng.annotations.Factory;
public class MyFactory {
@Factory
public Object[][] dp() {
Object[][] data = new Object[][] {
{ "1", "TestCase1", "Sample test 1" },
{ "2", "TestCase2", "Sample test 2" },
{ "3", "TestCase3", "Sample test 3" }
};
return data;
}
}
MyTest.java class:
package qa.tests;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class MyTest {
private String num;
private String name;
private String desc;
public MyTest(String num, String name, String desc) {
this.num = num;
this.name = name;
this.desc = desc;
}
@Test()
public void testSample1() {
System.out.println(num + ", " + name + ", " + desc);
assertTrue( true );
}
}
What in the world am I doing incorrectly?
First of all ,a Factory should return a one dimension Object array.
And that factory method should return instances of the test class that you are trying to execute.
So the factory will run your tests, if you change to this
public class MyFactory {
@Factory
public Object[] dp() {
Object[] data = new Object[] {
new MyTest("1", "TestCase1", "Sample test 1"), new Mytest("1", "TestCase1", "Sample test 1"), new MyTest("1", "TestCase1", "Sample test 1")
};
return data;
}
}
As per this error : either make it static or add a no-args constructor to your class
,
Your MyTest class need to have public no-args contructor, Java will not add the default constructor as you already have parametrized constructor, i.e public MyTest(String num, String name, String desc)
UPDATE
change your factory class
public class MyFactory {
@DataProvider(name = "MyData")
public static Object[][] dp(ITestContext context, Method m) throws Exception {
return new Object[][] { new Object[] { "1", "TestCase1", "Sample test 1" }};
}
@Factory(dataProvider = "MyData")
public Object[] createInstances(String num, String name, String desc) {
return new Object[] { new MyTest(num, name, desc) };
}
}
//Factory class supplying data to test
public class DataFactory {
@Factory
public Object[] DataSupplier(){
Object[] testData = new Object[3];
testData[0] = new FactoryTest(1);
testData[1] = new FactoryTest(2);
testData[2] = new FactoryTest(3);
return testData;
}
}
//Test class
public class FactoryTest {
int i;
public FactoryTest(int i) {
this.i = i;
}
@Test
public void f() {
System.out.println(i);
}
}
Testng.xml
<suite name="Suite">
<test name="Test">
<classes>
<class name="factorydata.DataFactory"/>
</classes>
</test> <!-- Test -->
</suite>
Datafactory class supplies the test data by creating instances of the test class and passing parameters to FactoryTest class constructor.
FactoryTest class consumes the data from the datafactory.
In the testng.xml refer the class which has factory , in this case it is DataFactory.
This explains a simple working TestNg Factory annotation usage.