Factory Annotation In TestNG: Today, we will discuss another important topic of TestNG, which Is @Factory Annotation On TestNG. Factory annotation marks a method as a factory and returns objects that TestNG will use as test classes, and the method will return must return Object[]. Factories allow you to create tests dynamically.
Why do we need @Factory Annotation?
Suppose a class has 2 test methods, and you want to run each test method ten times. Then, if someone asks you how you can do that, you may say that you will use the Invocationcount attribute inside the test method.
package com.softwaretestingo.testng.factoryannotation; import org.testng.annotations.Test; public class SimpleClassWithMultipleMethods { @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."); } }
Output:
Simple Test Method1. Simple Test Method2. Simple Test Method3. Simple Test Method4. Simple Test Method5.
In the above class, we can use the invocationCount, but when doing a complex scenario, it’s not recommended to use the invocationCount. Let’s take a situation:
For example, if you want to log in to softwareTestingo, with ten different user credentials and do some operation after login, you can’t do that with the InvocationCount attribute.
So, to handle such a complex scenario, this @Factory annotation is coming to a picture.
When to Use @Factory in Testng?
Sometimes, we get the requirement that we may need to run some set of different values, like, as I mentioned, logging 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.
However, the problem with this approach is that if you have 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 each test method five times, then we can do this.
package com.softwaretestingo.testng.factoryannotation; import org.testng.annotations.Factory; import org.testng.annotations.Test; 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 SimpleFactoryRunnerClass { @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; } }
Now, if you run the SimpleFactoryRunnerClass, you can see that each method of the SimpleFactoryRunnerClass class will be executed five times.
Output:
Simple Test Method1. Simple Test Method1. Simple Test Method1. Simple Test Method1. Simple Test Method1. Simple Test Method2. Simple Test Method2. Simple Test Method2. Simple Test Method2. Simple Test Method2. Simple Test Method3. Simple Test Method3. Simple Test Method3. Simple Test Method3. Simple Test Method3. Simple Test Method4. Simple Test Method4. Simple Test Method4. Simple Test Method4. Simple Test Method4. Simple Test Method5. Simple Test Method5. Simple Test Method5. Simple Test Method5. Simple Test Method5.
The Execution is based on the factory methods that return how many total object arrays. As in the above example, it returns five objects, so the Test class methods are executed five times each. If we have returned two objects, each method will be run 2 times.
TestNG Factory With Parameters
The main advantage of @Factory annotation is that you can pass the parameters to test classes while initializing them and 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.
package com.softwaretestingo.testng.factoryannotation; import org.testng.annotations.Factory; import org.testng.annotations.Test; class SimpleTestForParameters { private int param; public SimpleTestForParameters (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 SimpleFactoryRunnerClassWithParameters { @Factory public Object[] factoryMethod() { Object[] data = new Object[5]; data[0] = new SimpleTestForParameters(10); data[1] = new SimpleTestForParameters(20); data[2] = new SimpleTestForParameters(30); data[3] = new SimpleTestForParameters(40); data[4] = new SimpleTestForParameters(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.
Output:
Simple Test Method1 : 40 Simple Test Method1 : 20 Simple Test Method1 : 10 Simple Test Method1 : 50 Simple Test Method1 : 30 Simple Test Method2 : 40 Simple Test Method2 : 20 Simple Test Method2 : 10 Simple Test Method2 : 50 Simple Test Method2 : 30 Simple Test Method3 : 40 Simple Test Method3 : 20 Simple Test Method3 : 10 Simple Test Method3 : 50 Simple Test Method3 : 30 Simple Test Method4 : 40 Simple Test Method4 : 20 Simple Test Method4 : 10 Simple Test Method4 : 50 Simple Test Method4 : 30 Simple Test Method5 : 40 Simple Test Method5 : 20 Simple Test Method5 : 10 Simple Test Method5 : 50 Simple Test Method5 : 30
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, all the test methods can use that value.
Note: When you Execute the factory class, 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 continues until all the methods are executed.
With @Factory, we call the entire class an object with five different parameters.
Check this:
How to Use @Factory and @DataProvider in TestNG?
We can also use both @DataProvider and @Factory annotation at a time to create the tests at runtime. We can do this by declaring the @Factory annotation at the constructor or Method levels.
package com.softwaretestingo.testng.factoryannotation; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; 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); } }
In the above example, we have used the @Factory annotation at the constructor of a class. With this annotation, we have also used the DataProvider method to provide 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 parameter value passed to the test method per iteration. The said double object array contains two datasets with values 0 and 1.
Output:
Test method one output: 1 Test method one output: 2 Test method two output: 2 Test method two output: 3
TestNG @Factory – dependent tests
Earlier in this post, we have seen various implementations of the @Factory annotation. Still, we will now understand how to implement dependent tests and know the behavior.
package com.softwaretestingo.testng.factoryannotation; import org.testng.annotations.Factory; import org.testng.annotations.Test; 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 FactoryWithDependsOnMethods { @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, and later, the first method will execute.
That’s all related to @Factory annotation in TestNG. Let me know if you have any queries.
Frequently Asked Questions
When are you going to use the @Factory Annotation?
When you want to invoke the entire class in testNG, then, in that case, you can use the @Factory annotation.
What is the difference between DataProvider and @Factory annotation?
, we can say that DataProvider is meant to send parameters to the methods, Where the @Factory annotation invokes an entire TestNG test class repeatedly with different parameters.