Main Tutorials

TestNG – Parameter Test (XML and @DataProvider)

In this tutorial, we will show you how to pass parameters into a @Test method, via XML @Parameters or @DataProvider.

1. Passing Parameters with XML

In this example, the properties filename is passing from testng.xml, and inject into the method via @Parameters.

TestParameterXML.java

package com.mkyong.testng.examples.parameter;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class TestParameterXML {

	Connection con;

	@Test
	@Parameters({ "dbconfig", "poolsize" })
	public void createConnection(String dbconfig, int poolsize) {

		System.out.println("dbconfig : " + dbconfig);
		System.out.println("poolsize : " + poolsize);

		Properties prop = new Properties();
		InputStream input = null;

		try {
		  //get properties file from project classpath
		  input = getClass().getClassLoader().getResourceAsStream(dbconfig);

		  prop.load(input);

		  String drivers = prop.getProperty("jdbc.driver");
		  String connectionURL = prop.getProperty("jdbc.url");
		  String username = prop.getProperty("jdbc.username");
		  String password = prop.getProperty("jdbc.password");

		  System.out.println("drivers : " + drivers);
		  System.out.println("connectionURL : " + connectionURL);
		  System.out.println("username : " + username);
		  System.out.println("password : " + password);

		  Class.forName(drivers);
		  con = DriverManager.getConnection(connectionURL, username, password);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

}
db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mkyongserver
jdbc.username=mkyong
jdbc.password=password
testng.xml

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="test-parameter">

    <test name="example1">
	
	<parameter name="dbconfig" value="db.properties" />
	<parameter name="poolsize" value="10" />
		
	<classes>
	  <class name="com.mkyong.testng.examples.parameter.TestParameterXML" />
	</classes>
		
    </test>
	
</suite>

Output


dbconfig : db.properties
poolsize : 10
drivers : com.mysql.jdbc.Driver
connectionURL : jdbc:mysql://localhost:3306/mkyongserver
username : mkyong
password : password

2. Passing Parameters with @DataProvider

2.1 Review a simple @DataProvider example, passing a int parameter.

TestParameterDataProvider.java
package com.mkyong.testng.examples.parameter;

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class TestParameterDataProvider {

	@Test(dataProvider = "provideNumbers")
	public void test(int number, int expected) {
		Assert.assertEquals(number + 10, expected);
	}

	@DataProvider(name = "provideNumbers")
	public Object[][] provideData() {

		return new Object[][] { 
			{ 10, 20 }, 
			{ 100, 110 }, 
			{ 200, 210 } 
		};
	}

}

Output


PASSED: test(10, 20)
PASSED: test(100, 110)
PASSED: test(200, 210)

2.2 The @DataProvider is support passing an object parameter. Below example shows you how to pass a Map object as parameter.

TestParameterDataProvider.java

package com.mkyong.testng.examples.parameter;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class TestParameterDataProvider {

	@Test(dataProvider = "dbconfig")
	public void testConnection(Map<String, String> map) {

		for (Map.Entry<String, String> entry : map.entrySet()) {
		  System.out.println("[Key] : " + entry.getKey() 
                              + " [Value] : " + entry.getValue());
		}

	}

	@DataProvider(name = "dbconfig")
	public Object[][] provideDbConfig() {
		Map<String, String> map = readDbConfig();
		return new Object[][] { { map } };
	}

	public Map<String, String> readDbConfig() {

		Properties prop = new Properties();
		InputStream input = null;
		Map<String, String> map = new HashMap<String, String>();

		try {
		  input = getClass().getClassLoader().getResourceAsStream("db.properties");

		  prop.load(input);

		  map.put("jdbc.driver", prop.getProperty("jdbc.driver"));
		  map.put("jdbc.url", prop.getProperty("jdbc.url"));
		  map.put("jdbc.username", prop.getProperty("jdbc.username"));
		  map.put("jdbc.password", prop.getProperty("jdbc.password"));

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return map;

	}
	
}

Output


[Key] : jdbc.url [Value] : jdbc:mysql://localhost:3306/mkyongserver
[Key] : jdbc.username [Value] : mkyong
[Key] : jdbc.driver [Value] : com.mysql.jdbc.Driver
[Key] : jdbc.password [Value] : password
PASSED: testConnection({jdbc.url=jdbc:mysql://localhost:3306/mkyongserver, 
jdbc.username=mkyong, jdbc.driver=com.mysql.jdbc.Driver, jdbc.password=password})

3. @DataProvider + Method

This example shows you how to pass a different parameters depending on the test method name.

TestParameterDataProvider.java

package com.mkyong.testng.examples.parameter;

import java.lang.reflect.Method;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class TestParameterDataProvider {

	@Test(dataProvider = "dataProvider")
	public void test1(int number, int expected) {
		Assert.assertEquals(number, expected);
	}

	@Test(dataProvider = "dataProvider")
	public void test2(String email, String expected) {
		Assert.assertEquals(email, expected);
	}

	@DataProvider(name = "dataProvider")
	public Object[][] provideData(Method method) {

		Object[][] result = null;

		if (method.getName().equals("test1")) {
			result = new Object[][] {
				{ 1, 1 }, { 200, 200 } 
			};
		} else if (method.getName().equals("test2")) {
			result = new Object[][] { 
				{ "[email protected]", "[email protected]" }, 
				{ "[email protected]", "[email protected]" } 
			};
		}

		return result;

	}

}

Output


PASSED: test1(1, 1)
PASSED: test1(200, 200)
PASSED: test2("[email protected]", "[email protected]")
PASSED: test2("[email protected]", "[email protected]")

4. @DataProvider + ITestContext

In TestNG, we can use org.testng.ITestContext to determine what runtime parameters the current test method was invoked with. In this last example, we will show you how to pass parameters depending on the included group name.

TestParameterDataProvider.java

package com.mkyong.testng.examples.parameter;

import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class TestParameterDataProvider {

	@Test(dataProvider = "dataProvider", groups = {"groupA"})
	public void test1(int number) {
		Assert.assertEquals(number, 1);
	}

	@Test(dataProvider = "dataProvider", groups = "groupB")
	public void test2(int number) {
		Assert.assertEquals(number, 2);
	}

	@DataProvider(name = "dataProvider")
	public Object[][] provideData(ITestContext context) {

		Object[][] result = null;
	
		//get test name
		//System.out.println(context.getName());
		
		for (String group : context.getIncludedGroups()) {

			System.out.println("group : " + group);

			if ("groupA".equals(group)) {
				result = new Object[][] { { 1 } };
				break;
			}

		}

		if (result == null) {
			result = new Object[][] { { 2 } };
		}
		return result;

	}

}
testng.xml

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="test-parameter">

  <test name="example1">

	<groups>
		<run>
			<include name="groupA" />
		</run>
	</groups>

	<classes>
	   <class
	    name="com.mkyong.testng.examples.parameter.TestParameterDataProvider" />
	</classes>

  </test>

</suite>

Output


group : groupA

Done.

References

  1. TestNG @DataProvider
  2. TestNG ITestContext JavaDoc
  3. Connect To MySQL With JDBC Driver

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
15 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Saravanan
11 years ago

hi mkyoung,

this is article is awesome .And i need your inputs on running parallel testcases using paramters.

Thanks,
Saravanan Nallamuthu

Ashan Jayasundara
7 years ago

can we call after test method when throw an exception in data provider iteration

Tarek Said
9 years ago

Hi, just one thing: wouldn’t it be possible (and more manageable) to use 2 data providers for 2 methods? as in:

public class TestParameterDataProvider {
@Test(dataProvider = “numberProvider”)
public void test1(int number, int expectedNumber) {
Assert.assertEquals(number, expectedNumber);
}

@Test(dataProvider = “emailProvider”)
public void test2(String email, String expectedEmail) {
Assert.assertEquals(email, expectedEmail);
}

@DataProvider(name = “numberProvider”)
public Object[][] provideNumbers() {
return new Object[][] { { 1, 1 }, { 200, 200 } };
}

@DataProvider(name = “emailProvider”)
public Object[][] provideEmails() {
return new Object[][] {
{ “[email protected]”, “[email protected]” },
{ “[email protected]”, “[email protected]” }};
}

lixiao
9 years ago

If I want to use the way of ITestContext, I have to config the tag of groups in the testng.xml?
I found that the ITestContext.getIncludeGroups() can not get the value of groups if there is no testng.xml.

saran
9 years ago

For your example 2 the dataprovider takes its values from the java code itself.. Is there any possibility to load these values from the testng.xml

vertika
10 years ago

Hi ,

I am new to selenium. Is there any way if we can pass two Dataproviders in one function.

Please find below my code.

@DataProvider(parallel = true)

public static Iterator web_list (ITestContext context) throws IOException
{
List url = new ArrayList();
String webURL;
BufferedReader br = new BufferedReader(new FileReader(“WebList.txt”));
while( (webURL = br.readLine()) != null )
{
if( webURL.trim() != “”)
url.add(new Object[] {webURL});
}

return url.iterator();
}

@DataProvider(parallel = true)
public static Iterator browser_list (ITestContext context) throws IOException
{
List brw = new ArrayList();
String Browser;
BufferedReader br = new BufferedReader(new FileReader(“BrowserList.txt”));
while( (Browser = br.readLine()) != null )
{
if( Browser.trim() != “”)
brw.add(new Object[] {Browser});
}
return brw.iterator();
}

I want to pass above browser_list and web_list in one function.. I am trying like below..But I getting error in ‘@Test(dataProvider={ “web_list” , “browser_list” })’

@Test(dataProvider={ “web_list” , “browser_list” })
public void fun(String url, String browser) throws InterruptedException, MalformedURLException
{ }

Please help me how can I pass two different dataprovide values in one function.

Thanks in advance..

Manjyot
10 years ago

is there a way to print real arguments instead of : PASSED: parameterIntTest(TestNGTest6_3_0@dc6a77). For example desired output : PASSED: parameterIntTest(“Hello”,”123″)

Manjyot
10 years ago

Hi Mkyong,

Nice post I must say. There is one problem I am facing right now. It would be great if you can help me with that :
I am reading data from excel using data provider. Excel from which I am reading data is having some 25 odd columns and 250 odd rows. That means my test will be executed for 250 times with 25 arguments.. I am reading and returning Object[][] from data provider.
In turn I have declare so 25 arguments in my test method For example : @Test(groups = { “webservice” }, dataProvider = “testDP”)
public void testDP(String statusResponse,
String collateralized, String externalCIS, String fullName,
String hierarchy, String internalCIS, String limitAmount,
String limitCurrency, String limitId, String limitLevel,
String limitSource, String limitType, String locked,
String overrides, String parentCis, String parentFullName,
String parentLimitId, String parentPartyId, String partyId,
String displayString, String id, String name, String stream and so on……).
And the value of arguments are different for different test methods. All I want, is not to declare 25 arguments every time I am writing a test method, rather a approach similar to passing an object of class would be great. Some other solution will also work, if you can suggest…..

So example of what I want will be :
@Test(groups = { “webservice” }, dataProvider = “testDP”)
public void testDP(some_class obj)
{
//Then I can refer to variable values using obj
}

If I will take example of yours, then is there a way to do below :

@Test(dataProvider = “Data-Provider-Function”)
public void parameterIntTest(TestNGTest6_3_0 clzz) {
System.out.println(“Parameterized Number is : ” + clzz.getMsg());
System.out.println(“Parameterized Number is : ” + clzz.getNumber());
}

//This function will provide the patameter data
@DataProvider(name = “Data-Provider-Function”)
public Object[][] parameterIntTestProvider() {

TestNGTest6_3_0 obj = new TestNGTest6_3_0();
obj.setMsg(“Hello”);
obj.setMsg(“Hello123”); // Added

obj.setNumber(123);
obj.setNumber(456); // Added

return new Object[][]{
{obj}
};
}

I need to run test method 2 times as per my update and clzz object should be used to call getMsg and getNumber.

Thanks
MS

Sama
10 years ago

Im new to maven and testng
I got an issue: I cannot get parameter from suite xml file for my test when run Maven Test.
The result is this test is skipped:

——————————————————————————-
Test set: TestSuite
——————————————————————————-
Tests run: 1, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.375 sec

I dont know why
Anything wrong here?
I appreciate so much

Thank you

This is my main test: hTest.java
====

package demo;

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class hTest {

@Parameters({“user”})
@Test
public void getUser(String user)
{
System.out.println(“NAME= ” + user);
}

}

This is my suite hTest.xml

This is my pom.xml

4.0.0
test
sample
0.0.1-SNAPSHOT
BnS

test.suites

org.testng
testng
6.8.5

org.seleniumhq.selenium
selenium-java
2.33.0

org.seleniumhq.selenium
selenium-server
2.33.0

org.apache.maven.plugins
maven-surefire-report-plugin
2.14.1

${test.suite.dir}/hTest.xml

Piers
10 years ago

Hello MyKong

Do you have a tutorial for EVERYTHING???

Pradeep
10 years ago

Is there any short hand way (thru annotation) to pass parameter value directly without the testng.xml/DataProvider ?

Tester
10 years ago
Reply to  Pradeep

Try using @Optional annotation.

DQ
11 years ago

Thanks for sharing! For the DataProvider, do you have to hardcode all data in the Java class? Won’t that violate the use of xml configuration file?

Hemant
11 years ago

This one is Awesome !!Great help:)

Kiran C
14 years ago

I am using testng.xml to specify many different test parameters. For each test there is a name specified as part of the testng.xml format. How can I print out this name when the test method is running?