目录
什么是数据提供者?
数据提供程序及其返回的内容
DataProvider语法
@DataProvider注释的方法可以返回什么?
使用数据提供程序的测试用例
如何在测试用例中使用数据提供程序?
其他类中的数据提供程序
在@DataProvider带注释的方法中将方法作为参数传递
使用数据提供程序并行执行
使用数据提供程序的并行执行
TestNG为我们提供了许多特性来帮助我们简化自动化测试。其中一个特性是在TestNG中使用数据提供程序。
如果你想用不同的测试数据多次运行一个测试,你必须多次复制你的测试用例,并传递不同的数据给它。这将增加维护不同测试用例的复杂性。
@Test
public void test1() {
// with first test data
// do something
}
@Test
public void test2() {
// with second test data
// do something
}
@Test
public void test3() {
// with third test data
// do something
}
但是使用数据提供程序,我们可以使用不同的数据集多次运行单个案例。这将使我们的案件看起来更干净,更容易维护。
这篇文章将讨论以下主题-
- 什么是数据提供者?
- 数据提供程序及其返回的内容
- 使用数据提供程序的测试用例
- 其他类中的数据提供程序
- 在@DataProvider带注释的方法中将方法作为参数传递
- 使用数据提供程序并行执行
让我们一个一个来看。
什么是数据提供者?
TestNG中的数据提供程序是一种将参数传递到测试方法或测试用例中的方法。数据提供程序允许我们传递复杂的参数或复杂的对象(从属性文件或数据库读取的对象等)。
我们可以使用数据提供程序来提供测试所需的值。Data Provider是我们类中的一个方法,它使用@DataProvider注释进行注释,并返回一个对象数组的数组,或者我们可以说是一个2D数组。
数据提供程序及其返回的内容
DataProvider语法
@DataProvider(name = "dataprovider_name")
public Object[][] dataProviderMethod() {
return new Object[][] { { } };
}
- 如前所述,数据提供者是一个带@DataProvider注释的方法。
- @DataProvider annotation有一个name属性。
- name属性的值将成为数据提供程序的名称。
- 我们保留“dataprovider_name”作为数据提供者的名称。你可以保留任何你想要的名字。
- 如果我们不指定name属性,那么方法的名称将自动成为数据提供者的名称。
@DataProvider
public Object[][] dataProviderMethod() {
return new Object[][] { { } };
}
@DataProvider注释的方法可以返回什么?
它可以有两种返回类型-
- 一个是对象数组的数组或2维数组(Object[][])。这是创建数据提供程序时最常用的返回类型。
- 另一个是Iterator<Object[]>。
这篇文章将只讨论2维数组。
在一个2维数组中,行数表示一个测试用例应该运行多少次,列数表示一个测试用例运行的不同测试数据。
让我们创建一个数据提供器方法,它返回一个带有一些值的2维数组。
@DataProvider(name = "dataprovider_name")
public Object[][] dataProviderMethod() {
return new Object[][] {
{ "first", 2, 3 },
{ "second", 5, 6 },
{ "third", 8, 9 },
{ "fourth", 11, 12 }
};
}
使用上述数据提供程序的测试用例将执行4次,如行数所示。单行包含要作为测试用例参数传递的测试数据。
使用数据提供程序的测试用例
到目前为止,我们制作了一个数据提供者,但还没有使用过,所以,我们将使用上面的数据提供者制作一个测试方法。
如何在测试用例中使用数据提供程序?
- 所有测试方法都将使用@Test注释进行注释。
- @Test注释有一个名为“dataProvider”的属性。
- 我们可以在该属性中提供要使用的数据提供程序的名称。
- 2维数组列中的数据将成为我们测试用例的参数。
整个代码应该是这样的-
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class CodekruTest {
@DataProvider(name = "dataprovider_name")
public Object[][] dataProviderMethod() {
return new Object[][] {
{ "first", 2, 3 },
{ "second", 5, 6 },
{ "third", 8, 9 },
{ "fourth", 11, 12 }
};
}
@Test(dataProvider = "dataprovider_name")
public void test(String str, int a, int b) {
System.out.println("str = " + str + ", a = " + a + ", b = " + b);
}
}
test()方法现在将使用每行中提到的数据执行4次。下面是运行上述类后的输出。
str = first, a = 2, b = 3
str = second, a = 5, b = 6
str = third, a = 8, b = 9
str = fourth, a = 11, b = 12
PASSED: test("fourth", 11, 12)
PASSED: test("second", 5, 6)
PASSED: test("third", 8, 9)
PASSED: test("first", 2, 3)
其他类中的数据提供程序
在我们前面的例子中,测试用例和数据提供者在同一个类中,但是如果不是这样呢?如果数据提供程序在另一个类中怎么办?
下面是我们的项目结构
Demo
|_ _ CodekruTest
|_ _ DataProviderClass
Demo是包的名称,而CodekruTest包含测试用例,DataProviderClass包含数据提供程序。
如果数据提供程序在另一个类中,则它应满足以下条件之一,以便在另一个类的测试用例中使用。
- @DataProvider注释的方法应该是静态的。
- 或者,具有数据提供程序的类应该具有无参数构造函数。
如果一个方法不满足上述任何一个条件,它就不能在其他类的测试用例中用作数据提供者。
下面是我们的DataProviderClass,它有一个带@DataProvider注释的静态方法。
public class DataProviderClass {
@DataProvider(name = "dataprovider_name")
public static Object[][] dataProviderMethod() {
return new Object[][] {
{ "first", 2, 3 },
{ "second", 5, 6 },
{ "third", 8, 9 },
{ "fourth", 11, 12 }
};
}
}
使用上述数据提供程序的测试用例现在必须使用数据提供程序名称来提及数据提供程序类,如下所示。
@Test(dataProvider = "dataprovider_name", dataProviderClass = Demo.DataProviderClass.class)
public void test(String str, int a, int b) {
}
“dataProviderClass”属性采用实际数据提供程序方法所在的类名。
类名通常采用语法packageName1.packageName2.ClassName.class。在我们的例子中,类位于Demo包下,所以我们编写了Demo.DataProviderClass.class。
这是我们两个类。
public class CodekruTest {
@Test(dataProvider = "dataprovider_name", dataProviderClass = Demo.DataProviderClass.class)
public void test(String str, int a, int b) {
System.out.println("str = " + str + ", a = " + a + ", b = " + b);
}
}
public class DataProviderClass {
@DataProvider(name = "dataprovider_name")
public static Object[][] dataProviderMethod() {
return new Object[][] {
{ "first", 2, 3 },
{ "second", 5, 6 },
{ "third", 8, 9 },
{ "fourth", 11, 12 }
};
}
}
在执行CodekruTest类的测试用例后,我们将得到以下结果。
str = first, a = 2, b = 3
str = second, a = 5, b = 6
str = third, a = 8, b = 9
str = fourth, a = 11, b = 12
PASSED: test("fourth", 11, 12)
PASSED: test("second", 5, 6)
PASSED: test("third", 8, 9)
PASSED: test("first", 2, 3)
我们得到了和之前一样的结果。
在@DataProvider带注释的方法中将方法作为参数传递
到目前为止,我们还没有在@DataProvider注释的方法中传递任何参数。我们可以传递一个包含方法信息(如名称)的方法实例,并在@DataProvider注释的方法中访问它。
@DataProvider(name = "dataprovider_name")
public static Object[][] dataProviderMethod(Method method){
}
方法类属于java.lang.reflect包。
public class CodekruTest {
@DataProvider(name = "dataprovider_name")
public Object[][] dataProviderMethod(Method method) {
System.out.println("Method name: "+method.getName());
return new Object[][] {
{ "first", 2, 3 },
{ "second", 5, 6 },
{ "third", 8, 9 },
{ "fourth", 11, 12 }
};
}
@Test(dataProvider = "dataprovider_name")
public void test1(String str, int a, int b) {
System.out.println("str = " + str + ", a = " + a + ", b = " + b);
}
@Test(dataProvider = "dataprovider_name")
public void test2(String str, int a, int b) {
System.out.println("str = " + str + ", a = " + a + ", b = " + b);
}
}
执行上述方法后的输出-
Method name: test1
str = first, a = 2, b = 3
str = second, a = 5, b = 6
str = third, a = 8, b = 9
str = fourth, a = 11, b = 12
Method name: test2
str = first, a = 2, b = 3
str = second, a = 5, b = 6
str = third, a = 8, b = 9
str = fourth, a = 11, b = 12
我们可以看到方法名打印在这里。Method类提供了许多有用的方法,您可以根据需要使用它们。
使用数据提供程序并行执行
我们可以使用数据提供程序在不同的数据集上多次执行单个测试用例。默认情况下,数据提供程序将连续运行每个用例,这意味着直到最后一个用例没有完成,测试用例才会开始执行。
但是,如果我们谈论的是多个案例,执行所有案例可能需要时间。因此,为了加快执行速度,我们可以并行运行数据提供程序,这样2D数组的每一行都将并行运行。
使用数据提供程序的并行执行
我们必须使用@DataProvider注释的parallel属性,值为“true”。
@DataProvider(name = "dataprovider_name", parallel = true)
public Object[][] dataProviderMethod() {
return new Object[][] {{}};
}
这将并行处理这些案件。默认情况下,它可以并行运行10个案例。
如果我们想覆盖默认行为,我们必须在testng.xml文件中用“data-provider-thread-count
”属性定义它。
下面是XML文件,其中我们将“data-provider-thread-count
”值保持为2,这将只并行运行2个案例。
<suite name="codekru" data-provider-thread-count = "2">
<test name="codekruTest">
<classes>
<class name="Demo.CodekruTest" />
</classes>
</test>
</suite>