TestNG

TestNG Parameters Annotation Example

A TestNG based test method is like any other java method and is allowed to have parameters. @Parameters is the TestNG annotation that allows us to pass parameters to a Test method.

In this article, I am going to show you several examples of @Parameters annotation.

Before we start with the examples, a bit about the setup:

1. How to use a TestNG parameter?

  1. Define parameters in the testng.xml file.
  2. Refer those parameters in source files using @Parameters annotation.
  3. @Parameters annotation’s attribute value will hold the list of variables used to fill the parameters of this method
  4. Note that value is an optional attribute so you can skip it and straightaway specify the list of parameters

Let’s go through an example.

First, we will define the parameter in testng.xml using <parameter>. In the below XML, we define parameter exampleDesc, the name attribute holds the name of the parameter and the value attribute the value that we want to pass to the method.

testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
  <parameter name="exampleDesc" value="TestNG Parameter Example"></parameter>
	<test name="TestNgParametersTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestNgParameterExample" />
		</classes>
	</test>
</suite>

The @Parameters annotation is used for passing values to the method. In the below class, we have two test methods t1 and t2. Both the test methods have one string parameter. You can see the methods are annotated with @Parameters for passing the parameter value. Note that in case of t1, we have used value attribute to hold the list of parameter names whereas in case of method t2, we have directly specified the parameter name without the usage of value attribute.

TestNgParameterExample:

package com.javacodegeeks.testng.parameters;

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

public class TestNgParameterExample {
	
	@Parameters(value="exampleDesc")
	@Test
	public void t1(String desc) {
		System.out.println("t1: " + desc);
	}

	@Parameters("exampleDesc")
	@Test
	public void t2(String desc) {
		System.out.println("t2: " + desc);
	}
}

You can see from the output below, the parameter value specified in the XML file is received by the test methods.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testng.xml

t1: TestNG Parameter Example
t2: TestNG Parameter Example

===============================================
TestNgParametersSuite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

2. Null Parameter

If one of your test methods takes in a parameter, but you don’t specify its value in the XML file, then the TestNG will not run the test and instead skip with an error.

testngNullParameter.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<test name="TestNgParametersTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestNgParameterExample" />
		</classes>
	</test>
</suite>

When we run the above testng XML file, it complains of using a required parameter whose value is not defined . It suggests that we either define its value in XML file or mark it as @Optional. In the next section, we will see how to define a parameter with a default value.

Parameter is Required
TestNGException: Parameter is Required

3. Optional Parameter

TestNgOptionalParameterExample:

In the below example, we specify that the parameter is optional using @Optional. TestNG will pass in a specified default value, or null if none is specified. We specify a default value which we print in the test method.

package com.javacodegeeks.testng.parameters;

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

public class TestNgOptionalParameterExample {

	@Parameters("exampleDesc")
	@Test
	public void t(@Optional("TestNG Examples") String desc) {
		System.out.println(desc);
	}
}

testngOptionalParameter.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<test name="TestNgParametersTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestNgOptionalParameterExample" />
		</classes>
	</test>
</suite>

You can see in the below output, the optional value is printed.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngOptionalParameter.xml

TestNG Examples

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

4. Method with Multiple Parameters

You can also define a method with multiple parameters. They need to be specified comma separated in @Parameters annotation.

TestNgMultipleParameterExample:

package com.javacodegeeks.testng.parameters;

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

public class TestNgMultipleParameterExample {

	@Parameters({"category", "exampleDesc"})
	@Test
	public void t1(String category, String exampleDesc) {
		System.out.println("t1: " + category + ":" + exampleDesc);
	}
	
	@Parameters(value={"category", "exampleDesc", "moreDesc"})
	@Test
	public void t2(String category, String exampleDesc, String moreDesc) {
		System.out.println("t2: " + category + ":" + exampleDesc + ", " + moreDesc);
	}
}

testngMultipleParam.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<parameter name="category" value="JCG TestNG Category"></parameter>
	<parameter name="exampleDesc" value="TestNG Parameter Example"></parameter>
	<parameter name="moreDesc" value="Using value attribute"></parameter>
	<test name="TestNgParametersTest">
		<classes>
			<class name="com.javacodegeeks.testng.parameters.TestNgMultipleParameterExample" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngMultipleParam.xml

t1: JCG TestNG Category:TestNG Parameter Example
t2: JCG TestNG Category:TestNG Parameter Example, Using value attribute

===============================================
TestNgMultipleParametersSuite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

5. Parameter Types

TestNG will automatically try to convert the value specified in testng.xml to the type of your parameter. Here are the types supported:

  1. String
  2. int/Integer
  3. boolean/Boolean
  4. byte/Byte
  5. char/Character
  6. double/Double
  7. float/Float
  8. long/Long
  9. short/Short

In the below example, we have method t which takes in all the above parameters. These parameters are then defined in the testng XML file.

TestNgParameterTypesExample:

package com.javacodegeeks.testng.parameters;

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

public class TestNgParameterTypesExample {

	@Parameters({ "pString", "pInt", "pBoolean", "pByte", "pChar", "pDouble",
			"pFloat", "pLong", "pShort" })
	@Test
	public void t(String s, int i, boolean bo, byte b, char c, double d,
			float f, long l, short sh) {
		System.out.println("string: " + s + ", int: " + i + ", boolean: " + bo
				+ ", byte: " + b + ", char: " + c + ", double: " + d
				+ ", float: " + f + ", long: " + l + ", short: " + sh);
	}
}

testngParameterTypes.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<parameter name="pString" value="JCG" />
	<parameter name="pInt" value="1" />
	<parameter name="pBoolean" value="true" />
	<parameter name="pByte" value="2" />
	<parameter name="pChar" value="c" />
	<parameter name="pDouble" value="3.0" />
	<parameter name="pFloat" value="5.0" />
	<parameter name="pLong" value="4" />
	<parameter name="pShort" value="30" />
	<test name="TestNgParametersTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestNgParameterTypesExample" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngParameterTypes.xml

string: JCG, int: 1, boolean: true, byte: 2, char: c, double: 3.0, float: 5.0, long: 4, short: 30

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

6. Constructor with Parameters

The parameters can be defined even for the constructor as in the below example.

TestNgConstructorParameterExample:

package com.javacodegeeks.testng.parameters;

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

public class TestNgConstructorParameterExample {

	@Parameters("p")
	public TestNgConstructorParameterExample(String p) {
		System.out.println("TestNgConstructorParameterExample(" + p + ")");
	}

	@Test
	public void t() {
		System.out.println("test method: t");
	}
}

testngConstructorParam.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<parameter name="p" value="Constructor argument example"></parameter>
	<test name="TestNgParametersTest">
		<classes>
			<class name="com.javacodegeeks.testng.parameters.TestNgConstructorParameterExample" />
		</classes>
	</test>
</suite>

Output:

TestNgConstructorParameterExample(Constructor argument example)
[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngConstructorParam.xml

test method: t

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

7. Configuration methods with Parameters

We have seen using @Parameters annotation for the test methods and constructor. In the below example, we use it for the @BeforeTest configuration method.

TestNgConfigParameterExample:

package com.javacodegeeks.testng.parameters;

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

public class TestNgConfigParameterExample {
	
	@Parameters("param")
	@BeforeTest
	public void beforeTest(String p) {
		System.out.println("beforeTest parameter: " + p);
	}

	@Parameters("param")
	@Test
	public void t(String p) {
		System.out.println("test method t parameter: " + p);
	}
}

testngConfigParameter.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
  <parameter name="param" value="TestNG Parameter Example"></parameter>
	<test name="TestNgParametersTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestNgConfigParameterExample" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngConfigParameter.xml

beforeTest parameter: TestNG Parameter Example
test method t parameter: TestNG Parameter Example

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

8. Parameters in a Factory method

We can also use @Parameters annotation for a factory method like in the below example. Using the passed-in parameters, we create TestNgFactoryParameterExample test instance.

TestFactory:

package com.javacodegeeks.testng.parameters;

import org.testng.annotations.Factory;
import org.testng.annotations.Parameters;

public class TestFactory {
	
	@Factory
	@Parameters({"factory-param1", "factory-param2"})
	public Object[] create(String p1, String p2) {
		return new Object[]{new TestNgFactoryParameterExample(p1), new TestNgFactoryParameterExample(p2)};
	}
}

Note that in testng XML, we need to include the factory class TestFactory and not the test class as TestNG uses the factory class to create test instance.

testngFactoryParam.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
  <parameter name="factory-param1" value="Factory"></parameter>
  <parameter name="factory-param2" value="Example"></parameter>
	<test name="TestNgParametersTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestFactory" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngFactoryParam.xml

t: parameter passed by factory=Factory
t: parameter passed by factory=Example

===============================================
TestNgParametersSuite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

9. Parameter along with TestNG Injected Objects

In this example, we have used a parameter along with TestNG injected parameter Object ITestContext.

TestNgParamWithInjectedObjectsExample:

package com.javacodegeeks.testng.parameters;

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

public class TestNgParamWithInjectedObjectsExample {
	
	@Parameters("param")
	@Test
	public void t(String p, ITestContext context) {
		System.out.println("parameter: " + p + ", context: " + context.getName());
	}
}

testngParamWithInjectedObjects.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
  <parameter name="param" value="TestNG Parameter Example"></parameter>
	<test name="Parameter-Context-Test">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestNgParamWithInjectedObjectsExample" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngParamWithInjectedObjects.xml

parameter: TestNG Parameter Example, context: Parameter-Context-Test

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

10. Parameters passed to a static method

We can also define a TestNG method as a static method like the below example where beforeTest is a static method and it also receives a parameter.

StaticMethodParameterizationExample:

package com.javacodegeeks.testng.parameters;

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

public class TestNgStaticMethodParameterExample {
	
	@Parameters("param")
	@BeforeMethod
	public static void beforeTest(String p) {
		System.out.println("static beforeTest's parameter: " + p);
	}

	@Test
	public void t() {
		System.out.println("test method: t");
	}
}

testngStaticMethodParameter.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
  <parameter name="param" value="TestNG Parameter Example"></parameter>
	<test name="TestNgParametersTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.TestNgStaticMethodParameterExample" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngStaticMethodParameter.xml

static beforeTest's parameter: TestNG Parameter Example
test method: t

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

11. Overriding Parameters

We can define the parameters at <suite> level, <test> and <classes> level. TestNG will try to find the parameter first in the <classes> tag that contains the current class, and then, if it can’t find it, in the <test>. If it can’t find it even there, it will try to find it the <suite>.

We start the example with a testng XML which doesn’t override the parameter. It contains two parameters tag and param at suite level. We will next override it at test and classes level.

testngSuiteLevelParameter.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<parameter name="tag" value="TestNgOverrideParamExample"></parameter>
	<parameter name="param" value="SuiteLevel"></parameter>
	<test name="DontOverrideParamTest">
		<classes>
			<class name="com.javacodegeeks.testng.parameters.TestNgOverrideParamExample" />
		</classes>
	</test>
</suite>

This is our test class.

TestNgOverrideParamExample:

package com.javacodegeeks.testng.parameters;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class TestNgOverrideParamExample {
	
	@Parameters({"tag", "param"})
	@BeforeSuite
	public void beforeSuite(String tag, String p) {
		System.out.println(tag + ": beforeSuite parameter is at " + p);
	}
	
	@Parameters({"tag", "param"})
	@BeforeTest
	public void beforeTest(String tag, String p) {
		System.out.println(tag + ": beforeTest parameter is at " + p);
	}
	
	@Parameters({"tag", "param"})
	@BeforeClass
	public void beforeClass(String tag, String p) {
		System.out.println(tag + ": beforeClass parameter is at " + p);
	}

	@Parameters({"tag", "param"})
	@BeforeMethod
	public void beforeMethod(String tag, String p) {
		System.out.println(tag + ": beforeMethod parameter is at " + p);
	}
	
	@Parameters({"tag", "param"})
	@Test
	public void t(String tag, String p) {
		System.out.println(tag + ": t parameter is at " + p);
	}
}

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngSuiteLevelParameter.xml

TestNgOverrideParamExample: beforeSuite parameter is at SuiteLevel
TestNgOverrideParamExample: beforeTest parameter is at SuiteLevel
TestNgOverrideParamExample: beforeClass parameter is at SuiteLevel
TestNgOverrideParamExample: beforeMethod parameter is at SuiteLevel
TestNgOverrideParamExample: t parameter is at SuiteLevel

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

Now we override param in test.

testngOverrideSuiteWithTestParam.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<parameter name="param" value="SuiteLevel"></parameter>	
	<parameter name="tag" value="Example"></parameter>
	<test name="OverrideParamTest">
		<parameter name="param" value="TestLevel"></parameter>		
		<classes>			
			<class name="com.javacodegeeks.testng.parameters.TestNgOverrideParamExample" />
		</classes>
	</test>
</suite>

In the following output, you can see that only beforeSuite method prints the parameter defined at suite level, rest of the methods print the overridden value.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngOverrideSuiteWithTestParam.xml

Example: beforeSuite parameter is at SuiteLevel
Example: beforeTest parameter is at TestLevel
Example: beforeClass parameter is at TestLevel
Example: beforeMethod parameter is at TestLevel
Example: t parameter is at TestLevel

===============================================
TestNgParametersSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

Now we will override it in classes as well. We have two tests OverrideParamTest and DontOverrideParamTest. In OverrideParamTest, we override the value in test as well as classes. In DontOverrideParamTest, we override the value only in test and not in classes.

testngOverrideTestWithClassesParam.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgParametersSuite" parallel="false">
	<parameter name="param" value="SuiteLevel"></parameter>
	<parameter name="tag" value="Example1"></parameter>
	<test name="OverrideParamTest">
		<parameter name="param" value="TestLevel"></parameter>	    
		<classes>
			<parameter name="param" value="ClassesLevel"></parameter>
			<class name="com.javacodegeeks.testng.parameters.TestNgOverrideParamExample" />
		</classes>
	</test>
	<test name="DontOverrideParamTest">
		<parameter name="param" value="TestLevel"></parameter>
	    <parameter name="tag" value="Example2"></parameter>
		<classes>
			<class name="com.javacodegeeks.testng.parameters.TestNgOverrideParamExample" />
		</classes>
	</test>
</suite>

In the output here, you can see, the classes level parameter value overrides the test defined parameter.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\testngOverrideTestWithClassesParam.xml

Example1: beforeSuite parameter is at SuiteLevel
Example1: beforeTest parameter is at ClassesLevel
Example1: beforeClass parameter is at ClassesLevel
Example1: beforeMethod parameter is at ClassesLevel
Example1: t parameter is at ClassesLevel
Example2: beforeTest parameter is at TestLevel
Example2: beforeClass parameter is at TestLevel
Example2: beforeMethod parameter is at TestLevel
Example2: t parameter is at TestLevel

===============================================
TestNgParametersSuite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

12. Inheriting Parameters

In my final example, I show that the parameter values defined in the child suites inherit values from parent suite. A child suite can also override a parameter defined at parent suite.

Our test class contains test method inheritParameters with parameters param1 and param2.

TestNGParamInheritenceExample:

package com.javacodegeeks.testng.parameters;

import org.testng.annotations.Parameters;

import org.testng.annotations.Test;

public class TestNGParamInheritenceExample {
    @Test
    @Parameters({ "param1", "param2" })
    public void inheritParameters(String p1, String p2) {
        System.out.println("Inherited parameters: " + p1 + " " + p2);
    }
}

parentTestng.xml contains child suites child1Testng.xml and child2Testng.xml. We will override param1 in the child suites.

parentTestng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="ParameterSuite">
	<parameter name="param1" value="Parent"></parameter>
	<parameter name="param2" value="Suite"></parameter>
	<suite-files>
		<suite-file path="./child1Testng.xml" />
		<suite-file path="./child2Testng.xml" />
	</suite-files>
</suite>

child1Testng.xml overrides parameter param1.

child1Testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Child1Suite">
  <parameter name="param1" value="Child1"/>
  <test name="InheritedParamTest">  	
    <classes>
      <class name="com.javacodegeeks.testng.parameters.InheritedParamFromParentExample"/>
    </classes>
  </test>
</suite>

child2Testng.xml overrides parameter param1. It also contains another child suite child3Testng.xml.

child2Testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Child2Suite">
	<parameter name="param1" value="Child2" />
	<test name="InheritedParamTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.parameters.InheritedParamFromParentExample" />
		</classes>
	</test>
	<suite-files>
		<suite-file path="./child3Testng.xml" />
	</suite-files>
</suite>

Child suite child3Testng.xml again overrides parameter param1.

child3Testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Child3Suite">
  <parameter name="param1" value="Child3"/>
  <test name="InheritedParamTest">  	
    <classes>
      <class name="com.javacodegeeks.testng.parameters.InheritedParamFromParentExample"/>
    </classes>
  </test>
</suite>

In the below output, you can see the child suites manage to inherit as well as override the parameter values defined parent suite.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\child1Testng.xml

Inherited parameters: Child1 Suite

===============================================
Child1Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\child3Testng.xml

Inherited parameters: Child3 Suite

===============================================
Child3Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\child2Testng.xml

Inherited parameters: Child2 Suite

===============================================
Child2Suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

[TestNG] Running:
  C:\javacodegeeks_ws\testngParameters\src\test\resources\parentTestng.xml


===============================================
ParameterSuite
Total tests run: 3, Failures: 0, Skips: 0
===============================================

Download the Eclipse Project

In this article, I have shown you several examples of using the TestNG @Parameters annotation.

Download
You can download the full source code of this example here: testngParameters.zip

Ram Mokkapaty

Ram holds a master's degree in Machine Design from IT B.H.U. His expertise lies in test driven development and re-factoring. He is passionate about open source technologies and actively blogs on various java and open-source technologies like spring. He works as a principal Engineer in the logistics domain.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button