2009-03-20 31 views
18

Nos gustaría ejecutar algunas de nuestras pruebas cada una contra un conjunto de valores de datos, verificando que las mismas condiciones son ciertas para cada uno. Los datos se almacenan actualmente en archivos planos o en simples hojas de cálculo de Excel.Posible pasar parámetros a TestNG DataProvider?

Mi primera idea era crear un DataProvider TestNG que cargar los datos del archivo y ser usado para llamar al método de prueba una vez para cada valor de datos. Mi problema es que diferentes pruebas necesitan cargar datos de diferentes archivos y no parece haber ninguna forma de enviar un parámetro al DataProvider. ¿Alguien sabe si esto es posible?

Idealmente, me gustaría que mi código para parecerse a lo siguiente (ejemplo simplificado):

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)); 
    } 
} 

Respuesta

14

Tomado de the TestNG docs:

Si usted declara su @DataProvider como tomar una java.lang.reflect.Method como primer parámetro , TestNG pasará el método de prueba actual para este primer parámetro. Esto es particularmente útil cuando varios métodos de prueba usan el mismo @DataProvider y desea que devuelva diferentes valores según el método de prueba para el que suministra los datos.

Por ejemplo, el código siguiente muestra el nombre del método de ensayo en el interior de su @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) { 
} 

y por lo tanto de la pantalla:

test1 
test2 

Esto puede también ser combinado con la solución proporcionada por desolat para determinar los datos del contexto y el método en consecuencia:

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

La respuesta de yshua es un poco limitante porque todavía tiene que codificar los caminos de archivo dentro de su proveedor de datos. Esto significa que tendría que cambiar el código fuente y luego volver a compilar para volver a ejecutar la prueba. Esto frustra el propósito de usar archivos XML para configurar la ejecución de prueba.

Una mejor, definitivamente más hacky, kludge de una solución sería crear un método ficticio @test que se ejecute antes que el conjunto, tome sus rutas de archivo como parámetros y guarde esta información dentro de la Clase que aloja estos métodos de prueba.

Esta solución no es perfecta, pero hasta TestNG permite un mejor paso de parámetros (Tal vez esto ha cambiado), esto podría ser viable para sus necesidades.

+0

se podría inyectar tanto '' ITestContext' y method' (véase la parte inferior de la respuesta de "user64051") y ambos determinar los datos proporcionados a partir de parámetros _AND_ métodos de baño. Esto funciona en la versión actual y parece que ya funcionó en 5.14.x. –

17

Puede acceder a todos los parámetros definidos en su DataProvider usando TestNG's dependency injection capabilies. Se trata de un cierto ejemplo de DataProvider en la necesidad del parámetro "test_param":

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

Esto requiere "test_param" que se definirá en que 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> 

Véase el TestNG JavaDoc para obtener detalles sobre la clase ITestContext.

+0

Buena idea, pero probé esto y no funcionó para mí. Creo que puede ser porque estoy usando testng dentro del plugin maven surefire. – Jared

+1

para mí funciona con surefire 2.12 –

0

Para añadir a mi respuesta anterior, aquí está el código completo de cómo se puede hacer uso de Marco Easytest:

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

} 

Y así sucesivamente. Si usted quiere saber más acerca de cómo funciona la anotación @DataLoader en Easytest, mira el siguiente: https://github.com/EaseTech/easytest/wiki/EasyTest-:-Loading-Data-using-Excel

Tenga en cuenta que se puede utilizar XML, Excel, CSV o en su propio cargador de encargo para cargar los datos y todos pueden ser utilizado en la misma clase de prueba a la vez como se muestra en este ejemplo: https://github.com/EaseTech/easytest/blob/master/src/test/java/org/easetech/easytest/example/TestCombinedLoadingAndWriting.java

Espero que haya sido útil.

+0

Debe agregar esto a su otra respuesta en lugar de como una completamente nueva, o al menos eliminar su respuesta anterior. Y como se mencionó en @AndrewBarber, debería dejar en claro que este es su proyecto. – forresthopkinsa

1

Una forma más genérica de hacer esto sería hacer uso de la groups anotación para crear una lista personalizada de los valores:

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

Como alternativa, también puede crear su propia clase de anotación que se lleva en los elementos personalizados por lo que se podía hacer algo más como:

@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

Solución agradable y elegante, particularmente el segundo fragmento de código. Gracias. – Stuart

Cuestiones relacionadas