2009-03-20 5 views
18

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

Моя первая мысль заключалась в создании 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)); 
    } 
} 

ответ

14

Взятые из the TestNG docs:

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

Это может также быть объединен с раствором при условии путем дезолата для определения данных из контекста и соответствующего способа:

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

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

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

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

+0

можно впрыснуть как '' ITestContext' и Method' (см нижнюю часть ответа «user64051») и оба определяют предоставленные данные из ванной параметров _AND_ методов. Это работает в текущей версии, и похоже, что он уже работал в 5.14.x. –

17

Вы можете получить доступ ко всем определенным параметрам в вашем DataProvider, используя TestNG's dependency injection capabilies. Это несколько примеров 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> 

См TestNG JavaDoc подробную информацию о классе ITestContext.

+0

Хорошая идея, но я попробовал это, и это не сработало для меня. Я думаю, это может быть потому, что я использую testng внутри плагина maven surefire. – Jared

+1

для меня это работает с surefire 2.12 –

0

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

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

+0

Вы должны добавить это в свой другой ответ, а не как совершенно новый или, по крайней мере, удалить свой предыдущий ответ. И как сказал @AndrewBarber, вы должны четко указать, что это ваш проект. – forresthopkinsa

1

Более общий способ сделать это было бы использовать в 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 
} 
+0

Хорошее, элегантное решение, особенно второй фрагмент кода. Благодарю. – Stuart