Подтвердить что ты не робот

Можно передать параметры TestNG DataProvider?

Мы хотели бы выполнить некоторые из наших тестов каждый против набора значений данных, подтверждая, что одни и те же условия сохраняются для каждого из них. Данные в настоящее время хранятся либо в плоских файлах, либо в простых таблицах Excel.

Моя первая мысль заключалась в создании TestNG DataProvider, который будет загружать данные из файла и использоваться для вызова метода тестирования один раз для каждого значения данных. Моя проблема заключается в том, что в разных тестах необходимо загружать данные из разных файлов, и, похоже, не существует способа отправить параметр DataProvider. Кто-нибудь знает, возможно ли это?

В идеале я хотел бы, чтобы мой код выглядел следующим образом (упрощенный пример):

public class OddTest {
    @DataProvider(name = "excelLoader")
    public Iterator<Object[]> loadExcelData(String fileName) {
        ...
    }

    @Test(dataProvider = "excelLoader" dataProviderParameters = { "data.xls" })
    public void checkIsOddWorks(int num)
        assertTrue(isOdd(num));
    }
}
4b9b3361

Ответ 1

Вы можете получить доступ ко всем определенным параметрам в вашем DataProvider, используя TestNG-зависимые возможности инъекций. Это пример DataProvider, который нуждается в параметре "test_param":

@DataProvider(name = "usesParameter")
public Object[][] provideTestParam(ITestContext context) {
    String testParam = context.getCurrentXmlTest().getParameter("test_param");
    return new Object[][] {{ testParam }};
}

Для этого вам необходимо определить "test_param" suite.xml:

<!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 см. TestNG JavaDoc.

Ответ 2

Взято из Документы TestNG:

Если вы объявляете @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

Это также можно комбинировать с решением, предоставленным desolat, для определения данных из контекста и метода соответственно:

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

Ответ 3

Ответ от yshua немного ограничен, потому что вам все еще нужно жестко кодировать пути к файлу внутри вашего поставщика данных. Это означает, что вам придется изменить исходный код, а затем перекомпилировать, чтобы повторно запустить тест. Это нарушает цель использования файлов XML для настройки тестового прогона.

Лучше, определенно более взломанный, решение будет заключаться в создании метода dummy @test, который выполняется до набора, принимает ваши файловые пути как параметры и сохраняет эту информацию в классе, где хранятся эти методы тестирования.

Это решение не является совершенным, но до тех пор, пока TestNG не позволит лучше передать параметры (возможно, это изменилось), это может быть жизнеспособным для ваших нужд.

Ответ 4

Чтобы добавить к моему ответу выше, heres полный код того, как вы можете это сделать, используя 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"));

}

И так далее. Если вы хотите узнать больше о том, как аннотация @DataLoader работает в EasyTest, посмотрите на следующее: https://github.com/EaseTech/easytest/wiki/EasyTest-:-Loading-Data-using-Excel

Обратите внимание, что вы можете использовать XML, Excel, CSV или собственный пользовательский загрузчик для загрузки данных, и все они могут быть использованы в одном и том же тестовом классе одновременно, как показано в этом примере: https://github.com/EaseTech/easytest/blob/master/src/test/java/org/easetech/easytest/example/TestCombinedLoadingAndWriting.java

Надеюсь, это было полезно.

Ответ 5

Более общий способ сделать это - использовать аннотацию groups для создания пользовательского списка значений:

@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";
}

В качестве альтернативы вы также можете создать свой собственный класс аннотаций, который принимает пользовательские элементы, чтобы вы могли сделать что-то большее:

@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
}