web-dev-qa-db-fra.com

Écriture Java tests avec des fournisseurs de données

Je fais actuellement mon premier Java et j'aime le TDD entièrement. J'utilise JUnit pour écrire les tests. Apparemment, JUnit ne prend pas en charge fournisseurs de données =, ce qui rend plutôt ennuyeux de tester la même méthode avec 20 versions différentes d'un argument. Quel est l'outil de test le plus populaire/standard pour Java qui prend en charge les fournisseurs de données? Je suis tombé sur - TestNG , mais je n'ai aucune idée de sa popularité ou de sa comparaison avec les alternatives.

S'il existe un moyen d'obtenir ce comportement est une bonne façon d'utiliser JUnit, alors cela pourrait également fonctionner.

30
Jeroen De Dauw

JUnit 4 a un test paramétré qui fait la même chose que les fournisseurs de données php

@RunWith(Parameterized.class)
public class MyTest{ 
     @Parameters
    public static Collection<Object[]> data() {
           /*create and return a Collection
             of Objects arrays here. 
             Each element in each array is 
             a parameter to your constructor.
            */

    }

    private int a,b,c;


    public MyTest(int a, int b, int c) {
            this.a= a;
            this.b = b;
            this.c = c;
    }

    @Test
    public void test() {
          //do your test with a,b
    }

    @Test
    public void testC(){
        //you can have multiple tests 
        //which all will run

        //...test c
    }
}
29
dkatzel

Mes collègues de notre société ont écrit un DataProvider librement disponible dans le style TestNG pour JUnit que vous pouvez trouver sur github (https://github.com/TNG/junit-dataprovider) .

Nous l'utilisons dans de très grands projets et cela fonctionne très bien pour nous. Il présente certains avantages par rapport à Parameterized de JUnit car il réduira la surcharge des classes séparées et vous pouvez également exécuter des tests uniques.

Un exemple ressemble à ceci

@DataProvider
public static Object[][] provideStringAndExpectedLength() {
    return new Object[][] {
        { "Hello World", 11 },
        { "Foo", 3 }
    };
}

@Test
@UseDataProvider( "provideStringAndExpectedLength" )
public void testCalculateLength( String input, int expectedLength ) {
    assertThat( calculateLength( input ) ).isEqualTo( expectedLength );
}

Edit: Depuis la v1.7, il prend également en charge d'autres façons de fournir des données (chaînes, listes) et peut aligner le fournisseur afin qu'une méthode distincte ne soit pas nécessairement nécessaire.

Un exemple complet et fonctionnel peut être trouvé sur la page de manuel sur github. Il a également quelques fonctionnalités supplémentaires, comme la collecte des fournisseurs dans les classes utilitaires et leur accès à partir d'autres classes, etc. La page de manuel est très détaillée, je suis sûr que vous y trouverez des réponses aux questions.

41
Ingo Bürk

En fonction de vos besoins en flexibilité vs lisibilité, vous pouvez choisir Parameterized - l'option intégrée de junit, décrite par dkatzel. D'autres options sont des coureurs externes junit fournis par des bibliothèques externes comme zohhak , qui vous permettent de faire:

 @TestWith({
        "clerk,      45'000 USD, GOLD",
        "supervisor, 60'000 GBP, PLATINUM"
    })
    public void canAcceptDebit(Employee employee, Money money, ClientType clientType) {
        assertTrue(   employee.canAcceptDebit(money, clientType)   );
    }

ou junitParams avec des fonctionnalités un peu différentes. choisissez ce qui vous convient le mieux

7
piotrek

Voici une autre option. Vous n'avez pas besoin d'utiliser Google Guava, c'est juste ma mise en œuvre.

Cela utilise le même @Parameters comme réponse de @ dkatzel, mais au lieu que la classe prenne les arguments, le @Parameters l'annotation va sur des méthodes de test spécifiques, vous pouvez donc choisir quelles méthodes utiliser cet ensemble d'arguments.

import Java.util.Collection;

import com.google.common.collect.ImmutableList;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(JUnitParamsRunner.class)
public class FrobTester {
    @SuppressWarnings("unused")
    private Collection validfrobAndGorpValues() {
        return ImmutableList.of(
            new Object[] {"frob28953", 28953},
            new Object[] {"oldfrob-189-255", 1890255}
        );
    }

    @Test
    @Parameters(method = "validfrobAndGorpValues")
    public void whenGivenFrobString_thenGorpIsCorrect(
        String frobString,
        int expectedGorpValue
    ) {
        Frob frob = new Frob(frobString);
        Assert.assertEquals(expectedGorpValue, frob.getGorpValue());
    }
}
1
ErikE