Возможно ли передать параметры в TestNG DataProvider? - PullRequest
20 голосов
/ 20 марта 2009

Мы хотели бы выполнить некоторые из наших тестов, каждый из которых проводился с набором значений данных, проверяя, что одинаковые условия выполняются для каждого. В настоящее время данные хранятся в виде простых файлов или в простых электронных таблицах 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));
    }
}

Ответы [ 5 ]

17 голосов
/ 17 января 2011

Вы можете получить доступ ко всем определенным параметрам в вашем 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 .

16 голосов
/ 13 августа 2009

Взято из документа 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 голосов
/ 30 января 2016

Более общий способ сделать это - использовать аннотацию 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
}
1 голос
/ 02 марта 2010

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

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

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

0 голосов
/ 08 ноября 2012

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

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

...