DataProvider In TestNG: TestNg is a vibrant featured automation framework having lots of functionality like we can parametrise the configuration and test methods so that we can execute the same test method with a different set of input data. To Make it happen, we have to make that test method as a parametrised method, and we must pass the input value from somewhere.
We can do this in 2 ways:
- Parameters from testng.xml
- Parameters from DataProvider
We have already discussed a different way and how to implement parameters in testng class in our previous article. If you have not checked, then you can check by following this link.
Now one questions come to mind when we can use the parameters, then what’s the requirement of DataProvider.
- What are the factors to use DataProvider over testng.xml?
- When should we go for testng.xml or DataProvider or both?
Both the ways of providing parameters values in TestNG have their advantages. We will compare them here:
- For passing input data to a method, we can do that by mention the data in testng.xml and pass-through using the parameter. But if in future you need to change the input data then an automation tester can understand that easily. Still, you any manual testers are doing this job then it’s challenging to understand the XML file. But if you pass data from an Excel or properties file or Database, it will be easier to update data for anyone as per their required data to run tests. But the problem here is we can not read the data from an external source by using the parameter tag.
- If your automation script required multiple sets of data, then it’s not possible through testng.xml
- If the input data values are decided during the run time, then it is not possible in testng. Because we can not modify the testng.xml file at the runtime.
- You can pass any values, including the user-defined class type also, which is also not possible through testng.
What Is DataProvider?
- DataProvider is an annotation which is used to mark a method as a DataProvider, which provides data in the form of an array of objects and the data also can be used by configuration (@after & @before methods) and test method of a testng class.
- You can declare any method as a data provider by adding with method signature, by following this simple syntax:
@DataProvider(name=”Any name”) - A DataProvider method can have a name so that it can be used to supply data to test methods by just mentioning its name.
- A DataProvider annotated method always returns an array of objects. It can be any dimensional.
- The number of values passed by a data provider method should be equal to the number of attributes of the test method on which data provider method is used.
- If the attributes are not matching, then you will get an exception “org.testng.internal.reflect.MethodMatcherException: Data provider mismatch”.
- The main difference between passing data from the DataProvider method and passing data from testng.xml file, By using DataProvider, we can pass multiple sets data using DataProvider and test method will run on each set of data. But using parameters and testng.xml, it is not possible to pass multiple sets of data.
- If you are using DataProvider, you do not require testng xml to run it as we need to do in case of Parameters annotation.
Scenario 1: A data provider method which provides N set of single data:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderBasics1 { // You must need to mention data provider method name in Test method @Test(dataProvider="DataContainer") public void methodWithSingleAttribute(String a) { System.out.println(a); } // A data provider which will provide single value to a test method thrice. @DataProvider(name="DataContainer") public Object[] myDataProvider() { // Passing 3 set of data and each set contains single value Object data[]= new Object[3]; data[0]= "Make"; data[1]= "Selenium"; data[2]= "Easy"; return data; } }
Explanation:
- From the output, we have seen that the test method is run three times and each time it is counted as a separated test. That’s why the total test run count is three.
Why are we using Two Dimensional Array DataProvider Method?
Most of the time and also in some interviews, you face this question, why we are using a two-dimensional array with dataProvider. Before going to that, let us try to understand with a scenario:
Suppose in your locality a new office has opened. Suppose five employees joined their organisation. For that, they need to register new employees in their database, and for that, they have created an application. For complete registration purpose, they require that persons first name, last name, and phone number.
So the total requirement here is:
- Employees First, Last Name & Phone Number
- Five employees need to be registered
Table:
First_Name Last_name Email_ID
Mukesh Otwani Motwani@gmail.com
Amod Mahajan amahajan@hotmail.com
Animesh Prashant aprashant@gmail.com
Ankur Singh
asingh@gmail.com
Amritansh Kumar akumar@gmail.com
If you saw the above, you can find out each row represent a employees details, and each column represents a required input data like First, last name and phone number.
The same logic is applied in DataProvider also, As we store the data in an Excel file where we can find out each cell with the help of the cell details [row][column]. Thats why we are creating a two-dimensional array.
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderBasics2 { // You must need to mention data provider method name in Test method @Test(dataProvider="DataContainer") public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: "+First_name+" "+Last_Name+" "+Email_ID); } // A data provider method with return type as 2D array @DataProvider(name="DataContainer") public Object[] myDataProvider() { Object data[][]= new Object[5][3]; // First student details data[0][0]= "Mukesh"; data[0][1]= "Otwani"; data[0][2]= "Motwani@gmail.com"; // Second student details data[1][0]= "Amod"; data[1][1]= "Mahajan"; data[1][2]= "amahajan@hotmail.com"; // Third student details data[2][0]= "Animesh"; data[2][1]= "Prashant"; data[2][2]= "aprashant@gmail.com"; // Fourth student details data[3][0]= "Ankur"; data[3][1]= "Singh"; data[3][2]= "asingh@gmail.com"; // Fifth student details data[4][0]= "Amritansh"; data[4][1]= "Kumar"; data[4][2]= "akumar@gmail.com"; return data; } }
As in the above example, we have assigned the values by using the index, but we can also do the same thing by creating inline arrays like below:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderBasics3 { // You must need to mention data provider method name in Test method @Test(dataProvider="DataContainer") public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: "+First_name+" "+Last_Name+" "+Email_ID); } // A data provider method with return type as 2D array @DataProvider(name="DataContainer") public Object[] myDataProvider() { return new Object[][] { {"Mukesh", "Otwani", "Motwani@gmail.com"}, {"Amod","Mahajan","Amahajan@hotmail.com"}, {"Animesh","Prashant","aprashant@gmail.com"}, {"Ankur","Singh","asingh@gmail.com"}, {"Amritansh", "Kumar","akumar@gmail.com"} }; } }
How to Access DataProvider Methods From Another Class Test Class?
The previous example we have used the DataProvider method and test methods in a single class. But it is recommended to store data and test separately. So we can do that in 2 ways:
- Using Inheritance
- Static or Non-static DataProvider Methods
DataProvider Using Inheritance
This technique we can put the dataProvider method in a class and test method another class, but the test method class will extend the dataProvider class.
So when you execute, TestNg first looks at the same class for the dataProvider method, and if it is not found the dataProvider in testng class, then it will look in the dataProvider class.
DataProvider Class:
package DataProvider; import org.testng.annotations.DataProvider; public class DataProviderClass { // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public Object[] myDataProvider() { return new Object[][] { {"Mukesh", "Otwani", "Motwani@gmail.com"}, {"Amod","Mahajan","Amahajan@hotmail.com"}, {"Animesh","Prashant","aprashant@gmail.com"}, {"Ankur","Singh","asingh@gmail.com"}, {"Amritansh", "Kumar","akumar@gmail.com"} }; } }
TestNG Class:
package DataProvider; import org.testng.annotations.Test; // Extend DataProvider class public class DataProviderBasics3 extends DataProviderClass { // You must need to mention data provider method name in Test method @Test(dataProvider = "DataContainer") public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: " + First_name + " " + Last_Name + " " + Email_ID); } }
By Making Static or Non-static DataProvider Methods
If there is a requirement for extending a different class, then at a single place, you can not extend multiple class as multiple inheritances are not allowed in Java. In that case, you can create static or non-static DataProvider methods and can give it reference in TestNG class using “dataProviderClass” attribute in @Test method.
So when you are going to create static and when you need to create non-static methods?
If your DataProvider class has parameterised constructors, declare dataprovider methods as STATIC. If your DataProvider has default or no-argument constructor, you can declare data provide methods either static or non-static.
Below class has no constructor. So we can mark data provider method as static or non-static.
package DataProvider; import org.testng.annotations.DataProvider; public class DataProviderClass { // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public static Object[] myDataProvider() { return new Object[][] { { "Mukesh", "Otwani", "Motwani@gmail.com" }, { "Amod", "Mahajan", "Amahajan@hotmail.com" }, { "Animesh", "Prashant", "aprashant@gmail.com" }, { "Ankur", "Singh", "asingh@gmail.com" }, { "Amritansh", "Kumar", "akumar@gmail.com" } }; } }
OR
package DataProvider; import org.testng.annotations.DataProvider; public class DataProviderClass { // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public Object[][] myDataProvider() { return new Object[][] { { "Mukesh", "Otwani", "Motwani@gmail.com" }, { "Amod", "Mahajan", "Amahajan@hotmail.com" }, { "Animesh", "Prashant", "aprashant@gmail.com" }, { "Ankur", "Singh", "asingh@gmail.com" }, { "Amritansh", "Kumar", "akumar@gmail.com" } }; } }
TestNG Class
package DataProvider; import org.testng.annotations.Test; // Extend DataProvider class public class DataProviderBasics3 { // You must need to mention data provider method name in Test method @Test(dataProvider = "DataContainer", dataProviderClass = DataProviderClass.class) public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: " + First_name + " " + Last_Name + " " + Email_ID); } }
If your data provider class has parameterised constructor, you should declare the Data Provider method as static.
package DataProvider; import org.testng.annotations.DataProvider; public class DataProviderClass { DataProviderClass(String s) { System.out.println("I am parameterised constructor so you can not have non-sttaic data" + "provider methods"); } // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public static Object[][] myDataProvider() { return new Object[][] { { "Mukesh", "Otwani", "Motwani@gmail.com" }, { "Amod", "Mahajan", "Amahajan@hotmail.com" }, { "Animesh", "Prashant", "aprashant@gmail.com" }, { "Ankur", "Singh", "asingh@gmail.com" }, { "Amritansh", "Kumar", "akumar@gmail.com" } }; } }
TestNG Class:
package DataProvider; import org.testng.annotations.Test; // Extend DataProvider class public class DataProviderBasics3 { // You must need to mention data provider method name in Test method @Test(dataProvider = "DataContainer", dataProviderClass = DataProviderClass.class) public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: " + First_name + " " + Last_Name + " " + Email_ID); } }
Is It Mandatory To Have Return Type as Object in the DataProvider Method?
In our previous example we have seen the dataProvider is looking like below:
// A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public Object[] myDataProvider() { return new Object[][] { { "Mukesh", "Otwani", "Motwani@gmail.com" }, { "Amod", "Mahajan", "Amahajan@hotmail.com" }, { "Animesh", "Prashant", "aprashant@gmail.com" }, { "Ankur", "Singh", "asingh@gmail.com" }, { "Amritansh", "Kumar", "akumar@gmail.com" } }; }
As you can say that the return type of the method is a two-dimensional array, So one doubts comes into our mind is it compulsory that each method should a return type as an object only?
The answer to that, it is not mandatory that always the dataProvider should return a two-dimensional array. If all the data are string, then you can also return string as well.
Sample Java Code:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderWithReturnType { // You must need to mention data provider method name in Test method @Test(dataProvider = "DataContainer") public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: " + First_name + " " + Last_Name + " " + Email_ID); } // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public static String[][] myDataProvider() { return new String[][] { {"Mukesh", "Otwani", "Motwani@gmail.com"}, {"Amod", "Mahajan", "Amahajan@hotmail.com"}, {"Animesh", "Prashant", "aprashant@gmail.com"}, {"Ankur", "Singh","asingh@gmail.com"}, {"Amritansh", "Kumar", "akumar@gmail.com"} }; } }
Can The DataProvider Return Primitive data type?
Lets first see a sample program:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderWithReturnType { // You must need to mention data provider method name in Test method @Test(dataProvider = "DataContainer") public void studentRegistration(int n1, int n2, int n3) { System.out.println("n1 =" + n1 + " n2 =" + n2 + " n3 =" + n3); } // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public static int[][] myDataProvider() { return new int[][] { {1, 2, 3}, { 3, 4, 5} }; } }
If we run the above program where we are returning primitive data type, then we are getting ClassCastException exception. Let us update the same program with return type as a wrapper class.
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderWithReturnType { // You must need to mention data provider method name in Test method @Test(dataProvider = "DataContainer") public void studentRegistration(int n1, int n2, int n3) { System.out.println("n1 ="+n1 + " n2 ="+n2 +" n3 ="+n3); } // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public static Integer[][] myDataProvider() { return new Integer[][] { { 1,2,3 }, { 3,4,5} }; } }
The program executed successfully with our any error.
Note: You Can always use the return type as wrapper class, and if you have used the return type as primitive then you will get “ClassCastException”.
From all the above example, we got to know that a dataProvider method doesn’t need always to return only two-dimensional object array you can use other data types also. But the return type is an object is preferred when we need to return heterogeneous data — e.g. Integer, String, etc. all from one method.
Encapsulation with DataProvider Method?
Encapsulation is one of the critical OOPS concepts of Java Programming language, and It is nothing but binding related stuff together under one roof. It makes it simpler to users for doing operations like add, remove and modify members.
As on our previous example, we have mentioned about the registration process of an employee we need a few details like the first name. Last name and employee ID and we can do the registered them with the help of registration method, and we are doing all these operations by putting data member and member function putting on a single class.
By using that class and method, we can register as many employees as per our requirement, like below:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderBasics3 { // You must need to mention data provider method name in Test method @Test(dataProvider="DataContainer") public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: "+First_name+" "+Last_Name+" "+Email_ID); } // A data provider method with return type as 2D array @DataProvider(name="DataContainer") public Object[] myDataProvider() { return new Object[][] { {"Mukesh", "Otwani", "Motwani@gmail.com"}, {"Amod","Mahajan","Amahajan@hotmail.com"}, {"Animesh","Prashant","aprashant@gmail.com"}, {"Ankur","Singh","asingh@gmail.com"}, {"Amritansh", "Kumar","akumar@gmail.com"} }; } }
But Later, you get another new requirement that you need to mention the Gender of that employee also at the time of registration. So to achieve this, we need to modify the argument of dataprovider and test method.
It is a single argument so we can do that but if there is a requirement of add and remove the number of argument, then its too difficult to handle such a situation.
So, in this case, we can take the help of Encapsulation to Handle such type of modification in the programs.
So for the follow the steps:
- Create an employee class, where define the properties, methods for performing some operation and data getter and setter.
- Create another class having test and dataProvider methods
Employee Class:
package DataProvider; public class Student { String name; int age; String gender; public Student(String name, int age, String gender) { this.name= name; this.age=age; this.gender=gender; } // A method to check if student is eligible for registration public boolean validateAge() { if(this.age>2) { System.out.println("You are eligible to do registration."); return true; } else return false; } }
DataProvider class:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class StudentDataProvider { // A data provider method with return type as 2D array @DataProvider(name = "DataContainer") public static Student[] myDataProvider() { return new Student[] { new Student("Amod", 4, "Male"), new Student("Neha", 1, "Female") }; } // You must need to mention data provider method name in Test method @Test(dataProvider = "DataContainer") public void methodWithSingleAttribute(Student a) { if(a.validateAge()) { System.out.println("Student registered with details as Name = "+a.name + " , Age ="+a.age +" , Gender ="+a.gender); } else { System.out.println("Student not registered with details as Name = "+a.name + " , Age ="+a.age +" , Gender ="+a.gender); } } }
In the above dataProvider class, you can say that we are not returning any number of parameters, here we are returning an object. That solves our add or remove the argument problems. In this case, we do not need to modify the number of arguments in the caller test method.
Lazy Initialisation of DataProvider Method
Just we have seen if the number of arguments is more in dataProvider or if you don’t know the required number of data in advance or if the number of parameters is dynamic then its too difficult to handle such situations using dataProvider. Because in all these cases, we can not define the DataProvider method and Test method easily. All these problems can be solved using Iterator to a List of data.
As per the testNG Official documents:
An Iterator<Object[]>. The only difference with Object[][] is that an Iterator lets you create your test data lazily. TestNG will invoke the iterator, and then the test method with the parameters returned by this iterator one by one. This is particularly useful if you have a lot of parameter sets to pass to the method and you don’t want to create all of them upfront.
An array of objects (Object[]). This is similar to Iterator<Object[]> but causes the test method to be invoked once for each element of the source array.
An Iterator<Object>>. The lazy alternative of Object[]. Causes the test method to be invoked once for each element of the iterator.
That means in each iteration, we are getting a set of data for a test method.
Student CLass:
package DataProvider; public class Student { String name; int age; String gender; public Student(String name, int age, String gender) { this.name= name; this.age=age; this.gender=gender; } // A method to check if student is eligible for registration public boolean validateAge() { if(this.age>2) { System.out.println("You are eligible to do registration."); return true; } else return false; } }
DataProvider Class:
package DataProvider; import java.util.ArrayList; import java.util.Iterator; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderAndIterator { // A DataProvider method which returns an iterator to a list. @DataProvider(name="DataProviderIterator") public Iterator<Student> studentDetails(){ ArrayList<Student> s=new ArrayList<Student>(); s.add(new Student("Kiran", 28, "Male")); s.add(new Student("Amod", 28, "Male")); s.add(new Student("Anu", 28, "Female")); return s.iterator(); } // Test method accepting Student type attribute ( Not an Iterator) @Test(dataProvider = "DataProviderIterator") public void Studentregistration(Student student) { if(student.validateAge()) { System.out.println("Student registered with details as Name = "+student.name + " , Age ="+student.age +" , Gender ="+student.gender); } else { System.out.println("Student not registered with details as Name = "+student.name + " , Age ="+student.age +" , Gender ="+student.gender); } } }
You can see Iterator can remove the dependency of defining arguments in advance. You can easily add/remove/modify members and logics without worrying about the mismatch of arguments between the DataProvider method and Test method.
Parametrising DataProvider Method to Provide Data to Multiple Test Methods:
Previously we have seen the use of DataProvider With a single @test method, But now we are going to see how we can use a single DataProvider and multiple @test methods.
For the use of dataProvider, we can use separate dataProvider for each test method which is a simple way but manage multiple dataProvider when the count of test methods more is a difficult task. So to deal with such cases, we can parametrise the DataProvider method so that it will return the required data set as per the test method name.
Let us see how we can do this:
As per the Official Statement On TestNG Official website:
If you declare your @DataProvider as taking a java.lang.reflect.The method as the first parameter TestNG will pass the current test method for this first parameter. This is particularly useful when several test methods use the same @DataProvider, and you want it to return different values depending on which test method it is supplying data for.
That means when we pass a method name as the first parameter to the dataProvider method, that TestNG will pass the current test method name for this first parameter and based on that data we can decide what data need to be returned.
And there we can use the conditional block statements to accommodate the number of test methods as we know that the return type of a dataProvider is an Object[], which helps us to return a different set of data as well.
package DataProvider; import java.lang.reflect.Method; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; // Data class class India { public String getCapital() { return "New Delhi"; } } class USA { public String getCapital() { return "New York"; } } class UK { public String getCapital() { return "London"; } } public class CustomDataProvider { // A data provider method which will return a required data based on Test method // name @DataProvider(name = "DataContainer") public static Object[] myDataProvider(Method m) { // Matching test method name // You can use switch as well. if (m.getName().equals("India")) { India i[] = new India[1]; i[0] = new India(); return i; } else if (m.getName().equals("USA")) { USA i[] = new USA[1]; i[0] = new USA(); return i; } else if (m.getName().equals("UK")) { UK i[] = new UK[1]; i[0] = new UK(); return i; } else { System.out.println("No data found"); //System.exit(0); return null; } } // A test method @Test(dataProvider = "DataContainer") public void India(India capitalName) { System.out.println("Capital of India is " + capitalName.getCapital()); } // A test method @Test(dataProvider = "DataContainer") public void USA(USA capitalName) { System.out.println("Capital of USA is " + capitalName.getCapital()); } // A test method @Test(dataProvider = "DataContainer") public void UK(UK capitalName) { System.out.println("Capital of UK is " + capitalName.getCapital()); } }
Passing External Data File Name to DataProvider
The above discussion, we learn how we can pass test data from one DataProvider method to multiple methods, which helps us to get more benefits of TestNG. But now we are going to learn one more advance concept of TestNg which is how we can pass the external data file name to the dataProvider method using the TestNG XML.
As we know that for store test data permanent, we are using external files like Excel, Properties files. Where the external file name is not constant for example, an excel sheet can have multiple datasheets, and we pass the different datasheet name as per the requirement so we can not hardcoded the external file name in the script. Still, we can follow the below technique where we can use the concept of the parameter from testng.xml and DataProvider.
In TestNg We have an interface ITestContext, which is mainly used to store and share the data across the tests in testNg framework. So we can use the ITestContext in the dataProvider method as an attribute which can be used to read the data from the testng.xml and in this way we can pass the required file name data from testNG.xml to dataProvider method.
If the Data Filename changes, then we can do the same in the testng.xml file, and there is no need to make any changes in dataProvider methods.
Sample Class:
package DataProvider; import java.lang.reflect.Method; import org.testng.ITestContext; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class CustomDataProviderWithParameter { // A data provider method which will return a required data based on Test method // name @DataProvider(name = "DataContainer") public static Object[] myDataProvider(Method m, ITestContext iTestContext) { // Getting the method name String methodName = m.getName(); switch(methodName) { case "A" : { // Getting parameter value from testng.xml to get data file name for desired method String dataFilename= iTestContext.getCurrentXmlTest().getParameter("DataFileforA"); // I am returning data file name here but you can read data file and return proper data return new String[] {dataFilename}; } case "B" : { String dataFilename= iTestContext.getCurrentXmlTest().getParameter("DataFileforB"); return new String[] {dataFilename}; } case "C" : { String dataFilename= iTestContext.getCurrentXmlTest().getParameter("DataFileforC"); return new String[] {dataFilename}; } default: return new String[] {"No Data File"}; } } // A test method @Test(dataProvider = "DataContainer") public void A(String dataFilename) { System.out.println("DatafileName for method A is " + dataFilename); } // A test method @Test(dataProvider = "DataContainer") public void B(String dataFilename) { System.out.println("DatafileName for method B is " + dataFilename); } // A test method @Test(dataProvider = "DataContainer") public void C(String dataFilename) { System.out.println("DatafileName for method C is " + dataFilename); } }
TestNG Xml File:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Suite"> <parameter name="DataFileforA" value="methodA.xlsx" /> <parameter name="DataFileforB" value="methodB.xlsx" /> <parameter name="DataFileforC" value="methodC.xlsx" /> <test thread-count="5" name="Test"> <classes> <class name="DataProvider.CustomDataProviderWithParameter"/> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
Running the DataProvider Method in Parallel
We Had seen when the test method executed we got the execution order is the same as the data is passed from the dataprovider method. The reason behind this in the @DataProvider annotated method the attribute “parallel” is “false” which is the default value.
If you want to run parallel then you simple need to set the “parallel=true” in the dataprovider method. Like below:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderWithIndices { // You must need to mention data provider method name in Test method @Test(dataProvider="DataContainer") public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: "+First_name+" "+Last_Name+" "+Email_ID); } /* * Since we have set parallel as true, test method will be run in parallel for set of data provided by data provider. */ @DataProvider(name="DataContainer", parallel=true) public Object[] myDataProvider() { Object data[][]= new Object[5][3]; // First student details data[0][0]= "Mukesh"; data[0][1]= "Otwani"; data[0][2]= "Motwani@gmail.com"; // Second student details data[1][0]= "Amod"; data[1][1]= "Mahajan"; data[1][2]= "amahajan@hotmail.com"; // Third student details data[2][0]= "Animesh"; data[2][1]= "Prashant"; data[2][2]= "aprashant@gmail.com"; // Fourth student details data[3][0]= "Ankur"; data[3][1]= "Singh"; data[3][2]= "asingh@gmail.com"; // Fifth student details data[4][0]= "Amritansh"; data[4][1]= "Kumar"; data[4][2]= "akumar@gmail.com"; return data; } }
You can see console output is not in sequence of data provided by the DataProvider method. It means it was run parallel. Parallel data providers running from an XML file share the same pool of threads, which has a size of 10 by default. You can modify this value in the tag of your XML file:
<suite name=”Suite1″ data-provider-thread-count=”20″ >
Running Test for Specific Set of Data Provided by DataProvider Method
When we are running a testng class then that time a test method run for all data set returned by the dataprovider method because the dataProvider annotated method has an attribute called “indices” and the default value for that is “all”.
But we can modify that indices value and choose on which set of data we want to run out linked test method.
For Example, A DataProvider test method has five sets of data, and out of that, you want to run for 2 and 4. Then we can do that like the below program:
package DataProvider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderWithIndices { // You must need to mention data provider method name in Test method @Test(dataProvider="DataContainer") public void studentRegistration(String First_name, String Last_Name, String Email_ID) { System.out.println("Registered student with details: "+First_name+" "+Last_Name+" "+Email_ID); } // A data provider method with return type as 2D array // Data provider indices starts from zero. @DataProvider(name="DataContainer" , indices = {2,4}) public Object[] myDataProvider() { Object data[][]= new Object[5][3]; // First student details data[0][0]= "Mukesh"; data[0][1]= "Otwani"; data[0][2]= "Motwani@gmail.com"; // Second student details data[1][0]= "Amod"; data[1][1]= "Mahajan"; data[1][2]= "amahajan@hotmail.com"; // Third student details data[2][0]= "Animesh"; data[2][1]= "Prashant"; data[2][2]= "aprashant@gmail.com"; // Fourth student details data[3][0]= "Ankur"; data[3][1]= "Singh"; data[3][2]= "asingh@gmail.com"; // Fifth student details data[4][0]= "Amritansh"; data[4][1]= "Kumar"; data[4][2]= "akumar@gmail.com"; return data; } }
This feature is not more helpful as you need to go and edit in DataProvider method if you want to update indices.
This feature would have been more useful if :
- Indices are allowed to provide in Test annotated methods instead of DataProvider annotated method. It would help in maintaining less DataProvider methods for multiple Test methods.
- Indices are allowed to pass from testng xml.
Note:
- Index starts from zero, and if the data set is not present for the mentioned index, no error or exception will be thrown.
- Remember Indices are provided in DataProvider annotated method not Test annotated method.
Source: link
Read Excel Data Using DataProvider TestNG: How To Read Excel Data Using DataProvider TestNG Example Program?
package com.selenium.TestNG; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderExample1 { String Data; @Test(dataProvider="wpdata") public void wordpresslogin(String Uname,String PWD) throws InterruptedException { WebDriver driver=new FirefoxDriver(); driver.manage().window().maximize(); driver.get("https://www.odishaportals.in/wp-admin/"); driver.manage().timeouts().implicitlyWait(10000, TimeUnit.SECONDS); driver.findElement(By.id("user_login")).sendKeys(Uname); driver.findElement(By.id("user_pass")).sendKeys(PWD); driver.findElement(By.id("wp-submit")).click(); Thread.sleep(3000); driver.close(); } @DataProvider(name="wpdata") public Object[][] wordpressdata() { Object[][] Data=new Object[3][2]; Data [0][0]="test"; Data [0][1]="test1"; Data [1][0]="test2"; Data [1][1]="test2"; Data [2][0]="test"; Data [2][1]="test"; return Data; } }
Leave a Reply