web-dev-qa-db-fra.com

Possible de passer des paramètres à TestNG DataProvider?

Nous aimerions exécuter chacun de nos tests avec un ensemble de valeurs de données, en vérifiant que les mêmes conditions sont remplies pour chacun. Les données sont actuellement stockées dans des fichiers plats ou dans de simples feuilles de calcul Excel.

Ma première idée a été de créer un fournisseur de données TestNG capable de charger les données à partir du fichier et d’appeler la méthode de test une fois pour chaque valeur de données. Mon problème est que différents tests doivent charger des données à partir de différents fichiers et qu'il ne semble pas y avoir de moyen d'envoyer un paramètre au fournisseur de données. Est-ce que quelqu'un sait si c'est possible?

Idéalement, j'aimerais que mon code ressemble à ceci (exemple simplifié):

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));
    }
}
20
Benjamin Lee

Vous pouvez accéder à tous les paramètres définis dans votre fournisseur de données à l'aide de Les capacités d'injection de dépendance de TestNG . Voici un exemple de DataProvider nécessitant le paramètre "test_param":

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

Ceci nécessite que "test_param" soit défini dans votre 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>

Voir le TestNG JavaDoc pour plus de détails sur la classe ITestContext.

17
desolat

Tiré de de la documentation TestNG

Si vous déclarez votre @DataProvider comme prenant un Java.lang.reflect.Method en tant que premier paramètre, TestNG passera la méthode de test actuelle pour ce premier paramètre. Ceci est particulièrement utile lorsque plusieurs méthodes de test utilisent le même @DataProvider et que vous souhaitez qu'il renvoie des valeurs différentes en fonction de la méthode de test pour laquelle il fournit des données.

Par exemple, le code suivant affiche le nom de la méthode de test dans son @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) {
}

et affichera donc:

test1
test2

Ceci peut également être combiné avec la solution fournie par desolat pour déterminer les données à partir du contexte et de la méthode en conséquence:

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

Une façon plus générique de le faire serait d'utiliser l'annotation groups pour construire une liste personnalisée de valeurs:

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

Alternativement, vous pouvez également créer votre propre classe d'annotation qui intègre des éléments personnalisés afin de pouvoir faire quelque chose de plus similaire à:

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

La réponse de yshua est un peu limitée car vous devez encore coder en dur les chemins de fichiers dans votre fournisseur de données. Cela signifie que vous devrez changer le code source, puis recompiler pour simplement relancer le test. Cela empêche l'utilisation de fichiers XML pour configurer l'exécution du test. 

Une solution meilleure, et certainement plus astucieuse, consisterait à créer une méthode factice @test qui s'exécute avant la suite, prend vos chemins de fichiers en tant que paramètres et enregistre ces informations dans la classe contenant ces méthodes de test.

Cette solution n’est pas parfaite, mais jusqu’à ce que TestNG permette un meilleur paramétrage (cela a peut-être changé), cela pourrait être viable pour vos besoins.

1
esiegel

Pour ajouter à ma réponse ci-dessus, voici le code complet de la procédure à suivre à l'aide de 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"));

}

Et ainsi de suite. Si vous souhaitez en savoir plus sur le fonctionnement de l'annotation @DataLoader dans EasyTest, consultez les éléments suivants: https://github.com/EaseTech/easytest/wiki/EasyTest-:- Chargement de données avec Excel

Notez que vous pouvez utiliser XML, Excel, CSV ou votre propre chargeur personnalisé pour charger les données et que tous peuvent être utilisés simultanément dans la même classe de test, comme indiqué dans cet exemple: https://github.com/EaseTech/easytest /blob/master/src/test/Java/org/easetech/easytest/example/TestCombinedLoadingAndWriting.Java

J'espère que c'était utile.

0
Anuj