Utiliser les DataProviders de TestNG sous Junit4

Un DataProvider permet de déclarer une liste de ressources à passer à des tests unitaires. Ces tests sont joués pour chaque élément de cette liste (cela nous évite de coder un « for »). Cette fonctionnalité, issue de TestNG, peut être portée vers JUnit4 via la librairie https://github.com/TNG/junit-dataprovider. Et c’est compatible Spring Framework.

De l’intérêt du DataProvider

Qu’est-ce qu’un DataProvider

Un DataProvider permet de lancer un test unitaire en lui fournissant des données en entrée, ces données prenant la forme de paramètres à la méthode du test unitaire. Il est par exemple possible de définir une liste de noms-prénoms à une méthode testant une inscription.

Un DataProvider est biensûr réutilisable.

Enfin, il se présente sous la forme d’un tableau à une ou deux dimensions pour associer plusieurs données à chaque exécution de test, par exemple une liste de noms et prénoms.

Un exemple de DataProvider sera parlant :

@DataProvider
public static Object[][] dataProviderPeople() {
    return new Object[][]{
            {"John", "Karmac"},
            {"Bob", "Dylan"},
            {"Dexter", "Holland"}
    };
}

Nous avons ici un DataProvider déclarant trois couples nom-prénom.

Voici comment l’utiliser :

@Test
@UseDataProvider(value = "dataProviderPeople")
public void shouldRegister(String name, String surname) throws Exception {

Ce test sera exécuté 3 fois, les paramètres « name » et « surname » valant respectivement John Karmac, Bob Dylan, puis Dexter Holland.

Tester des jeux de données sans DataProvider

Sans DataProvider, nous aurions été tentés de définir le jeu de données quelque part, puis déclarer une boucle « for » (ou un « foreach » sous Java 8) dans le test unitaire, celui-ci étant donc exécuté une seule fois.

Un problème survient : si une des itérations met le test en échec, vous ne saurez pas immédiatement laquelle. Vous devrez lancer le test avec un debugger ou bien consulter des logs. Bref, vous allez perdre du temps.

Améliorer ses tests avec des DataProviders

Avec le DataProvider vu plus haut, c’est la méthode de test sera exécutée 3 fois. En cas d’échec, nous saurons donc quel couple prénom-nom est fautif.

Avec cette implémentation du test :

@Test
@UseDataProvider(value = "dataProviderPeople")
public void shouldRegister(String name, String surname) throws Exception {
    if (name.equalsIgnoreCase("BOB")) {
        fail("pour l'article");
    }
}

Voici un exemple d’exécution depuis IntelliJ IDEA :

exécution depuis IntelliJ IDEA

 

Les données fautives sont clairement identifiées.

Pour information, cela reprend la présentation des données que nous aurions eu avec TestNG.

Comment utiliser un DataProvider sous JUnit4

Installer junit-dataprovider

Déclarer la dépendance envers « com.tngtech.java:junit-dataprovider ».

Exemple Maven :

<dependencies>
	<!-- ... -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>com.tngtech.java</groupId>
		<artifactId>junit-dataprovider</artifactId>
		<version>1.12.0</version>
		<scope>test</scope>
	</dependency>
	<!-- ... -->
</dependencies>

Exemple Gradle :

repositories {
    mavenCentral()
}
dependencies {
    // …
    testCompile
group: ‘junit’, name: ‘junit’, version: ‘4.12’
    testCompile
group: ‘com.tngtech.java’, name: ‘junit-dataprovider’, version: ‘1.12.0’
    
// …
}

(Ces exemples sont repris de https://github.com/TNG/junit-dataprovider/wiki/Getting-started#download)

Déclarer et utiliser un DataProvider

Un DataProvider permet de définir de 1 à n valeurs sur chaque ligne. Exemple :

@DataProvider
public static Object[][] dataProviderUnNom() {
    return new Object[][]{
            {val_1a, val_1b, val_1c,},
            {val_2a, val_2b, val_2c,},};
}

Il est possible de nommer le DataProvider de plusieurs façons :

  • Nommez-le de la même façon qu’un test unitaire pour qu’il lui soit automatiquement associé (explications sur https://github.com/TNG/junit-dataprovider/wiki/Features#convention-over-configuration)
  • Nommez-le comme bon vous semble. Le DataProvider pourra être associé à tous les tests unitaires portant l’annotation adéquate : @UseDataProvider(value = « nom du dataprovider »)
  • La page https://github.com/TNG/junit-dataprovider/wiki/Features#customize-test-method-name vous propose de nombreuses autres façons de nommer et associer vos DataProviders

Enfin, vous pouvez insérer des objets de tout type. Vous pouvez par exemple passer un nom « String » et un âge « int ». Le DataProvider déclarera un tableau d’« Objects », et les tests unitaires déclareront des paramètres « String » et « int ».

Une limitation à connaître

Attention aux données que vous placez dans vos DataProviders. En effet, leur initialisation se produit avant l’invocation des méthodes @Before de JUnit. Vous ne pourrez donc pas directement utiliser des données générées dans une phase @Before.

Lancer les tests JUnit

Pour être compatibles avec les DataProviders, vos classes de test doivent utiliser le runner adéquat :

@RunWith(DataProviderRunner.class)

Comment utiliser un DataProvider avec un Runner Spring sous JUnit4

Vous lancez probablement vos classes de test avec un runner Spring tel que « SpringJUnit4ClassRunner », et vous savez que JUnit ne permet pas d’en utiliser deux en même temps.

Les développeurs de junit-dataprovider fournissent un runner personnalisé réunissant les fonctionnalités des deux runners « SpringJUnit4ClassRunner » et « DataProviderRunner ». Copiez la classe DataProviderRunnerWithSpring.java dans votre projet et utilisez simplement le runner « DataProviderRunnerWithSpring ».

Exemple :

@RunWith(DataProviderRunnerWithSpring.class)
@SpringBootTest(classes = Application.class, webEnvironment = RANDOM_PORT)
public class SampleTest {

J’ai pu le tester avec succès sur une pile Spring Boot récente (1.5.x) dotée de la plupart des modules habituels (Boot, Web, WS, Security, Data, Batch) tant en ligne de commande qu’avec IntelliJ IDEA 2016.3.5.

 

Ce sujet vous intéresse ?

NOUS CONTACTER