是否可以将参数传递给TestNG数据提供程序?

是否可以将参数传递给TestNG数据提供程序?,testng,data-driven-tests,Testng,Data Driven Tests,我们希望针对一组数据值分别运行一些测试,以验证相同的条件是否适用于每个测试。数据当前存储在平面文件或简单的Excel电子表格中 我的第一个想法是创建一个TestNG数据提供者,它将从文件中加载数据,并用于为每个数据值调用一次测试方法。我的问题是,不同的测试需要从不同的文件加载数据,并且似乎没有任何方法将参数发送到数据提供程序有人知道这是否可行吗? 理想情况下,我希望我的代码如下所示(简化示例): 公共类测试{ @数据提供者(name=“excelLoader”) 公共迭代器loadExcelDa

我们希望针对一组数据值分别运行一些测试,以验证相同的条件是否适用于每个测试。数据当前存储在平面文件或简单的Excel电子表格中

我的第一个想法是创建一个TestNG数据提供者,它将从文件中加载数据,并用于为每个数据值调用一次测试方法。我的问题是,不同的测试需要从不同的文件加载数据,并且似乎没有任何方法将参数发送到数据提供程序有人知道这是否可行吗?

理想情况下,我希望我的代码如下所示(简化示例):

公共类测试{
@数据提供者(name=“excelLoader”)
公共迭代器loadExcelData(字符串文件名){
...
}
@测试(dataProvider=“excelLoader”dataProviderParameters={“data.xls”})
公共无效检查ISODDWorks(整数)
资产净值(isOdd(num));
}
}
摘自:

如果将@DataProvider声明为将
java.lang.reflect.Method
作为第一个参数,TestNG将通过第一个参数的当前测试方法。当多个测试方法使用相同的@DataProvider,并且您希望它根据为哪个测试方法提供数据返回不同的值时,这一点特别有用

例如,以下代码在其@DataProvider中打印测试方法的名称:

@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) {
}
因此将显示:

test1
test2
这也可以与SALOST提供的解决方案相结合,根据上下文和相应的方法确定数据:

    @DataProvider(name = "dp")
    public Object[][] foodp(ITestContext ctx, Method method) {
        // ...
    }

yshua的答案有点局限性,因为您仍然需要在数据提供程序中硬编码文件路径。这意味着您必须更改源代码,然后重新编译以重新运行测试。这违背了使用XML文件配置测试运行的目的

一个更好的、肯定更黑客的、乱七八糟的解决方案是创建一个在suite之前运行的虚拟@test方法,将您的文件路径作为参数,并将此信息保存在包含这些测试方法的类中


此解决方案并不完美,但在TestNG允许更好的参数传递之前(可能已经改变),这可能适合您的需要。

您可以使用访问数据提供程序中所有定义的参数。这是一些需要“test_param”参数的示例数据提供程序:

@DataProvider(name = "usesParameter")
public Object[][] provideTestParam(ITestContext context) {
    String testParam = context.getCurrentXmlTest().getParameter("test_param");
    return new Object[][] {{ testParam }};
}
这需要在您的
suite.xml
中定义“test_param”:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite">
    <parameter name="test_param" value="foo" />
    <test name="tests">
        <classes>
            ...
        </classes>
    </test>
</suite>

...

有关ITestContext类的详细信息,请参见。

要添加到我的上述答案中,以下是如何使用EasyTest Framework执行此操作的完整代码:

@RunWith(DataDrivenTestRunner.class)
public class MyTestClass {

@Test
@DataLoader(filePaths={myTestFile.xls}, loaderType=LoaderType.EXCEL)
public void testFirstMethod(@Param()
Map<String, Object> inputData) {
    System.out.print("Executing testFirstMethod:");
    System.out.println("library Id : " + inputData.get("LibraryId"));

}

@Test
@DataLoader(filePaths={mySecondTestFile.xls}, loaderType=LoaderType.EXCEL)
public void testSecondMethod(@Param(name="input")
MyClassObject inputData) {
    System.out.print("Executing testSecondMethod:");
    System.out.println("library Id : " + inputData.get("LibraryId"));

}
@RunWith(DataDrivenTestRunner.class)
公共类MyTestClass{
@试验
@DataLoader(文件路径={myTestFile.xls},loaderType=loaderType.EXCEL)
public void testFirstMethod(@Param()
地图输入(数据){
System.out.print(“正在执行testFirstMethod:”);
System.out.println(“库Id:+inputData.get(“库Id”);
}
@试验
@数据加载器(文件路径={mySecondTestFile.xls},loaderType=loaderType.EXCEL)
public void testSecondMethod(@Param(name=“input”)
MyClassObject(输入数据){
System.out.print(“正在执行testSecondMethod:”);
System.out.println(“库Id:+inputData.get(“库Id”);
}
等等。 如果您想进一步了解@DataLoader注释在EasyTest中的工作原理,请参阅以下内容:

请注意,您可以使用XML、Excel、CSV或您自己的自定义加载程序加载数据,并且所有数据都可以一次在同一测试类中使用,如本例所示:


我希望它有用。

一种更通用的方法是使用
注释来构建自定义值列表:

@DataProvider(name = "excelLoader")
public Object[][] createData(Method m) {
    ArrayList<Object[]> excelFiles = new ArrayList<Object[]>;
    // iterate over all the groups listed in the annotation
    for (String excelFile : ((Test) m.getAnnotation(Test.class)).groups()) {
        // add each to the list
        excelFiles.add(new Object[] { excelFile });
    }
    // convert the list to an array
    return excelFiles.toArray(new Object[excelFiles.size()]);
}

@Test(dataProvider = "excelLoader", groups = { "data1", "data2" })
public void test1(String excelFile) {
    // we will test "data1.xls" and "data2.xls" in this test
    String testExcelFile = excelFile + ".xls";
}

@Test(dataProvider = "excelLoader", groups = { "data2", "data3" })
public void test2(String excelFile) {
    // we will test "data2.xls" and "data3.xls" in this test
    String testExcelFile = excelFile + ".xls";
}
@DataProvider(name=“excelLoader”)
公共对象[][]createData(方法m){
ArrayList excelFiles=新建ArrayList;
//迭代注释中列出的所有组
对于(字符串excelFile:((Test)m.getAnnotation(Test.class)).groups()){
//将每个添加到列表中
添加(新对象[]{excelFile});
}
//将列表转换为数组
返回excelFiles.toArray(新对象[excelFiles.size()]);
}
@测试(dataProvider=“excelLoader”,groups={“data1”,“data2”})
公共void test1(字符串文件){
//在这个测试中,我们将测试“data1.xls”和“data2.xls”
字符串testExcelFile=excelFile+“.xls”;
}
@测试(dataProvider=“excelLoader”,groups={“data2”,“data3”})
公共void test2(字符串文件){
//在这个测试中,我们将测试“data2.xls”和“data3.xls”
字符串testExcelFile=excelFile+“.xls”;
}
或者,您也可以创建自己的注释类,该类接受自定义元素,以便您可以执行以下操作:

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD, TYPE, CONSTRUCTOR})
public @interface FilesToTest {
    public String[] value() default {};
}

@DataProvider(name = "excelLoader")
public Object[][] createData(Method m) {
    ArrayList<Object[]> excelFiles = new ArrayList<Object[]>;
    // iterate over all the groups listed in the annotation
    for (String excelFile : ((FilesToTest) m.getAnnotation(FilesToTest.class)).value()) {
        // add each to the list
        excelFiles.add(new Object[] { excelFile });
    }
    // convert the list to an array
    return excelFiles.toArray(new Object[excelFiles.size()]);
}

@Test(dataProvider = "excelLoader")
@FilesToTest({ "data1.xls", "data2.xls" })
public void myTest(String excelFile) {
    // we will test "data1.xls" and "data2.xls" in this test
}
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@目标({方法、类型、构造函数})
public@interface FilesToTest{
公共字符串[]值()默认值{};
}
@数据提供者(name=“excelLoader”)
公共对象[][]createData(方法m){
ArrayList excelFiles=新建ArrayList;
//迭代注释中列出的所有组
对于(字符串excelFile:((FilesToTest)m.getAnnotation(FilesToTest.class)).value()){
//将每个添加到列表中
添加(新对象[]{excelFile});
}
//将列表转换为数组
返回excelFiles.toArray(新对象[excelFiles.size()]);
}
@测试(dataProvider=“excelLoader”)
@FilesToTest({“data1.xls”、“data2.xls”})
公共void myTest(字符串文件){
//在这个测试中,我们将测试“data1.xls”和“data2.xls”
}

好主意,但我尝试了这个方法,但它对我无效。我想可能是因为我在maven surefire插件中使用了testng。有人能告诉我一个解决方案吗?你应该将它添加到你的其他答案中,而不是作为一个全新的答案,或者至少删除你以前的答案
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD, TYPE, CONSTRUCTOR})
public @interface FilesToTest {
    public String[] value() default {};
}

@DataProvider(name = "excelLoader")
public Object[][] createData(Method m) {
    ArrayList<Object[]> excelFiles = new ArrayList<Object[]>;
    // iterate over all the groups listed in the annotation
    for (String excelFile : ((FilesToTest) m.getAnnotation(FilesToTest.class)).value()) {
        // add each to the list
        excelFiles.add(new Object[] { excelFile });
    }
    // convert the list to an array
    return excelFiles.toArray(new Object[excelFiles.size()]);
}

@Test(dataProvider = "excelLoader")
@FilesToTest({ "data1.xls", "data2.xls" })
public void myTest(String excelFile) {
    // we will test "data1.xls" and "data2.xls" in this test
}