Factory Annotation In TestNG: Today, we are going to discuss another important topic of TestNG, which Is @Factory Annotation On TestNG. Factory annotation marks a method as factory and returns objects what will be used by TestNG as test classes, and the method will return must return Object[]. Factories allow you to create tests dynamically.
Why we need @Factory Annotation?
Suppose there is a class having 2 test methods, and you want to run each test method for ten times. Then if someone asks you how you can do that, you maybe say that you are going to use the Invocationcount attribute inside the test method.
public class SimpleTest { @Test public void simpleTest1() { System.out.println(“Simple Test Method1.”); } @Test public void simpleTest2() { System.out.println(“Simple Test Method2.”); } @Test public void simpleTest3() { System.out.println(“Simple Test Method3.”); } @Test public void simpleTest4() { System.out.println(“Simple Test Method4.”); } @Test public void simpleTest5() { System.out.println(“Simple Test Method5.”); } }
In the above class, we can use the invocationCount, but when you are doing to the complex scenario, then its not recommended to use the invocationCount. Let’s take a situation:
You want to login to softwareTestingo, with ten different user credentials and do some operation after login, then you can’t do that with InvocationCount attribute.
So for handle such a complex scenario, this @Factory annotation is coming to a picture.
When to Use @Factory in Testng?
Sometimes we got the requirement like we may need to run some set of different values like as I mention login into the application with ten different credentials.
We can achieve this by defining a separate set of tests inside a suite in testng.xml, and with that, we can test the required scenario. But the problem with this approach is that if you got an extra set of input data, then you need to redefine the test. We can solve such problems by using the @factory annotation feature.
How to Declare a Factory Method Syntax?
@Factory public Object[] factoryMethod() { Object [] data=new Object[5]; return data; }
Basic TestNG @Factory Example:
Now let us try to execute the above class test method for five-times, then we can do this.
public class SimpleTest { @Test public void simpleTest1() { System.out.println("Simple Test Method1."); } @Test public void simpleTest2() { System.out.println("Simple Test Method2."); } @Test public void simpleTest3() { System.out.println("Simple Test Method3."); } @Test public void simpleTest4() { System.out.println("Simple Test Method4."); } @Test public void simpleTest5() { System.out.println("Simple Test Method5."); } } public class FactoryClass { @Factory public Object[] factoryMethod() { Object [] data=new Object[5]; data[0]= new SimpleTest(); data[1]= new SimpleTest(); data[2]= new SimpleTest(); data[3]= new SimpleTest(); data[4]= new SimpleTest(); return data; } }
chk this:
Now, if you run the FactoryClass class, then you can see that each method of SimpleTest class will be executed five times. The Execution is based on how the factory methods return many total object arrays. As in the above example, it returns five objects, so the Test class methods executed five times each. If we have return two objects, then each method will be run 2 times.
TestNG factory parameters
The main advantage of @Factory is you can pass the parameters to test classes while you are initializing them, and you can use those parameters across all test methods.
Let’s take the same example and see how to modify the class so that it can make the parameters.
public class SimpleTest { private int param; public SimpleTest (int param) { this.param=param; } @Test public void simpleTest1() { System.out.println("Simple Test Method1." + param)); } @Test public void simpleTest2() { System.out.println("Simple Test Method2." + param)); } @Test public void simpleTest3() { System.out.println("Simple Test Method3." + param)); } @Test public void simpleTest4() { System.out.println("Simple Test Method4." + param)); } @Test public void simpleTest5() { System.out.println("Simple Test Method5." + param)); } } public class FactoryClass { @Factory public Object[] factoryMethod() { Object [] data=new Object[5]; data[0]= new SimpleTest(10); data[1]= new SimpleTest(20); data[2]= new SimpleTest(30); data[3]= new SimpleTest(40); data[4]= new SimpleTest(50); return data; } }
For this example, in the test class, we have created a constructor to initialize the class variable and use that variable in all different @Test methods.
From the output, you can see that each of the @test methods is executed 5 times and whatever the parameters passed while initializing using the test class that can be used by all the test methods.
Note: When you Execute the factory class, then each method of the test class is executed for all the parameters of the Factory class. The next method will be executed for all the parameters of the Factory class, and the process is going on until all the methods got executed.
So we are calling the entire class as an object with five different parameters.
So now we hope you got the answer for when you are going to use the @Factory Annotation?
Ans: When you want to invoke the entire class in testNG, then, in that case, you can use the @Factory annotation.
Then the next questions that will arise in your mind are: What is the different between DataProvider and @Factory annotation?
In simple words, we can say that DataProvider is meant to send for parameters to the methods, Where the @Factory annotation to invoke an entire testng test class again and again with different parameters.
How to Use @Factory and @DataProvider in TestNG?
We can also use both @DataProvider and @Factory annotation at a time for creating the tests at runtime. We can be done this by declaring the @Factory annotation at the constructor level or on Method Level.
public class DataProviderTest { private int param; @Factory(dataProvider = "dataMethod") public DataProviderTest(int param) { this.param = param; } @DataProvider public static Object[][] dataMethod() { return new Object[][] { { 0 }, { 1 } }; } @Test public void testMethodOne() { int opValue = param + 1; System.out.println("Test method one output: " + opValue); } @Test public void testMethodTwo() { int opValue = param + 2; System.out.println("Test method two output: " + opValue); } }
The above example, we have used the @Factory annotation at the constructor of a class. With this annotation, we have used the DataProvider method as well for providing the value to the constructor for initializing the variables.
The DataProvider method returns a double object array in which the first array represents the dataset, which decides the number of times the test will be iterated. In contrast, the second array is the actual parameter value that will be passed to the test method per iteration. The said double object array contains two datasets with values 0 and 1.
TestNG @Factory – dependent tests
Earlier in this post, we have seen various implementation about the @Factory annotation. Still, now we are going to understand how we can implement with dependent tests and know the behaviour also.
public class DependencyTest { private int param; public DependencyTest(int param) { this.param = param; } @Test(dependsOnMethods = { "testMethodTwo" }) public void testMethodOne() { System.out.println("Test method one with param values: " + this.param); } @Test public void testMethodTwo() { System.out.println("Test method two with param values: " + this.param); } } public class SimpleTestFactory { @Factory public Object[] factoryMethod() { return new Object[] { new DependencyTest(1), new DependencyTest(2) }; } }
The above Test class contains two methods, and test method one depends on test method 2. So when you call the first test method as it depends on the execution result of the second method, the second method will execute first later, the first method will execute.
That’s all related to @Factory annotation in TestNG. Let me know if you have any queries.
Source: Link
Leave a Reply