Hello, I'm brother gang.
As an extremely powerful testing framework of Java technology stack, TestNG must also have some special features in parameterization. This paper will explore TestNG parameterization according to the official documents.
There are two ways to parameterize TestNG. The first is from TestNG XML reads data, and the second is to read data through code.
From TestNG XML reading data
Look directly at the example:
@Parameters({ "first-name" }) @Test public void testSingleString(String firstName) { System.out.println("Invoked testString " + firstName); assert "Cedric".equals(firstName); }
<suite name="My suite"> <parameter name="first-name" value="Cedric"/> <test name="Simple example"> <-- ... -->
-
@Parameters specifies the name of the parameterization.
-
The test method input parameter names correspond one by one.
-
testng. < parameter > defines parameterized values in XML.
In TestNG In XML, < parameter > can be defined either in < suite > or < test >. If there is a parameter with the same name, it will overwrite < suite > with < test >.
@Parameters can act on @ Test, @ Before/After and @ Factory, for example:
@Parameters({ "datasource", "jdbcDriver" }) @BeforeMethod public void beforeTest(String ds, String driver) { m_dataSource = ...; // look up the value of datasource m_jdbcDriver = driver; }
It can also be used in the construction method of the test class, but there can only be one construction method at most, so that the parameterized assignment can be carried out when initializing the class, which is convenient for the use of the test method
@Optional is used to identify whether the parameter is optional, for example:
@Parameters("db") @Test public void testNonExistentParameter(@Optional("mysql") String db) { ... }
- If the db parameter cannot get a name, the mysql value will be taken.
Read data through code
The first parameterization method is actually a chicken's rib. The second method is the soul of TestNG parameterization. When @ DataProvider is used, it will return a two-dimensional array:
import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DPTest { @DataProvider(name = "test1") public Object[][] createData1() { return new Object[][] { { "Cedric", 36}, { "Anne", 37}, }; } @Test(dataProvider = "test1") public void verifyData1(String n1, Integer n2) { System.out.println(n1 + " " + n2); } }
- @DataProvider is used for production data. name is the unique identifier.
- Specify the name in @ Test through the dataProvider property.
- The input parameters of the test method correspond to the elements in the array one by one.
The default @ DataProvider and @ Test are in the same class. If you want to put them in different classes, you need to define them as static methods (or classes without parameter construction methods), such as:
import org.testng.annotations.DataProvider; public class StaticProvider { @DataProvider(name = "create") public static Object[][] createData() { return new Object[][] { new Object[] {42} }; } }
import org.testng.annotations.Test; public class DiffClazzTest { @Test(dataProvider = "create", dataProviderClass = StaticProvider.class) public void test(Integer n) { System.out.println(n); } }
- createData() is static.
- You need to specify the class of @ DataProvider through the dataProviderClass attribute of @ Test.
@The return value (parameter type) of DataProvider can be iterator < Object [] > in addition to the already mentioned Object [] []. It will not generate all data at once, but once every call to save memory, such as:
import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Iterator; public class IterTest { @DataProvider(name = "test1") public Iterator<Object[]> createData1() { Object[][] myObjects = new Object[][]{ {"Cedric", 36}, {"Anne", 37}, }; return Arrays.asList(myObjects).iterator(); } @Test(dataProvider = "test1") public void verifyData1(String n1, Integer n2) { System.out.println(n1 + " " + n2); } }
Seeing this, I have a good understanding of @ DataProvider, which supports two parameter types:
- Object[][]
- Iterator<Object[]>
If the test method has only one input parameter, can it only be realized in two dimensions:
import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Iterator; public class IterTest { @DataProvider(name = "test1") public Iterator<Object[]> createData1() { Object[][] myObjects = new Object[][]{ {"x"}, {"y"} }; return Arrays.asList(myObjects).iterator(); } @Test(dataProvider = "test1") public void verifyData1(String n) { System.out.println(n); } }
In fact, @ DataProvider supports one-dimensional arrays:
import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Iterator; public class IterTest { @DataProvider(name = "test1") public Object[] createData1() { Object[] myObjects = new Object[]{ "x", "y" }; return myObjects; } @Test(dataProvider = "test1") public void verifyData1(String n) { System.out.println(n); } }
And iterators for one-dimensional arrays:
import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Iterator; public class IterTest { @DataProvider(name = "test1") public Iterator<Object> createData1() { Object[] myObjects = new Object[]{ "x", "y" }; return Arrays.asList(myObjects).iterator(); } @Test(dataProvider = "test1") public void verifyData1(String n) { System.out.println(n); } }
The most wonderful thing is that @ DataProvider supports reflection, that is, reverse obtaining the information of the test method:
@DataProvider(name = "dp") public Object[][] createData(Method m) { System.out.println(m.getName()); // print test method name return new Object[][] { new Object[] { "Cedric" }}; } @Test(dataProvider = "dp") public void test1(String s) { } @Test(dataProvider = "dp") public void test2(String s) { }
- The input parameter of createData is Java lang.reflect. Method, so that you can get the information of the test method. For example, getName() here will get test1 and test2 in turn.
@DataProvider also supports Concurrency:
@DataProvider(parallel = true) // ...
The default is 10 threads, which can be in TestNG Modify in XML:
<suite name="Suite1" data-provider-thread-count="20" > ...
One XML shares one thread pool. If you want to use multiple thread pools, you need to create multiple TestNG xml.
The icing on the cake is that the parameterization of TestNG will be printed in the test report:
reference material:
https://testng.org/doc/documentation-main.html 5.6 - Parameters