Essai de JUnit avec nombre dynamique d'essais

dans notre projet, j'ai plusieurs tests JUnit qui, par exemple, prennent chaque fichier d'un répertoire et exécutent un test sur lui. Si je mets en œuvre une méthode testEveryFileInDirectory dans le TestCase cela apparaît comme un seul test qui peut échouer ou réussir. Mais je suis intéressé par les résultats sur chacun des fichiers. Comment puis-je écrire un TestCase / TestSuite de telle sorte que chaque fichier apparaisse comme un test séparé, par exemple dans le TestRunner graphique D'Eclipse? (Codage d'une méthode d'essai explicite pour chaque fichier n'est pas une option.)

comparez aussi la question ParameterizedTest avec un nom dans Eclipse Testrunner .

90
demandé sur Community 2008-12-11 12:39:45

7 réponses

regardez Paramétrée Tests dans JUnit 4.

en fait j'ai fait ça il y a quelques jours. Je vais essayer de l'expliquer ...

construisez D'abord votre classe de test normalement, comme vous juste tester avec un fichier d'entrée. Décorer votre classe avec:

@RunWith(Parameterized.class)

construire un constructeur qui prend l'entrée qui va changer dans chaque appel de test (dans ce cas, il peut être le fichier lui-même)

ensuite, construisez une méthode statique qui retournera un Collection de tableaux. Chaque tableau de la collection contiendra les arguments d'entrée pour votre constructeur de classe, par exemple le fichier. Décorer cette méthode avec:

@Parameters

Voici un exemple de classe.

@RunWith(Parameterized.class)
public class ParameterizedTest {

    private File file;

    public ParameterizedTest(File file) {
        this.file = file;
    }

    @Test
    public void test1() throws Exception {  }

    @Test
    public void test2() throws Exception {  }

    @Parameters
    public static Collection<Object[]> data() {
        // load the files as you want
        Object[] fileArg1 = new Object[] { new File("path1") };
        Object[] fileArg2 = new Object[] { new File("path2") };

        Collection<Object[]> data = new ArrayList<Object[]>();
        data.add(fileArg1);
        data.add(fileArg2);
        return data;
    }
}

cochez également cette case exemple

95
répondu bruno conde 2012-09-14 09:24:22

JUnit 3

public class XTest extends TestCase {

    public File file;

    public XTest(File file) {
        super(file.toString());
        this.file = file;
    }

    public void testX() {
        fail("Failed: " + file);
    }

}

public class XTestSuite extends TestSuite {

    public static Test suite() {
        TestSuite suite = new TestSuite("XTestSuite");
        File[] files = new File(".").listFiles();
        for (File file : files) {
            suite.addTest(new XTest(file));
        }
        return suite;
    }

}

JUnit 4

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class TestY {

    @Parameters
    public static Collection<Object[]> getFiles() {
        Collection<Object[]> params = new ArrayList<Object[]>();
        for (File f : new File(".").listFiles()) {
            Object[] arr = new Object[] { f };
            params.add(arr);
        }
        return params;
    }

    private File file;

    public TestY(File file) {
        this.file = file;
    }

    @Test
    public void testY() {
        fail(file.toString());
    }

}
27
répondu McDowell 2008-12-11 11:04:15

Junit 5 Parameterized Tests

JUnit 5 les essais paramétrisés soutiennent ceci en permettant l'utilisation d'une méthode comme source de données :

@ParameterizedTest
@MethodSource("fileProvider")
void testFile(File f) {
    // Your test comes here
}

static Stream<File> fileProvider() {
    return Arrays.asList(new File(".").list()).stream();
}

JUnit 5 DynamicTests

JUnit 5 l'appuie également par la notion d'un DynamicTest , qui doit être généré dans un @TestFactory , par moyen de la méthode statique dynamicTest .

import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;

import java.util.stream.Stream;

@TestFactory
public Stream<DynamicTest> testFiles() {
    return Arrays.asList(new File(".").list())
            .stream()
            .map((file) -> dynamicTest(
                    "Test for file: " + file,
                    () -> { /* Your test comes here */ }));
}

les tests effectués dans votre IDE (IntelliJ ici) seront affichés comme ceci:

Output in IntelliJ

6
répondu avandeursen 2018-09-08 17:26:10

devrait être possible en juin 3 en héritant de TestSuite et en supplantant la méthode tests() pour lister les fichiers et pour chaque retour une instance d'une sous-classe de TestCase qui prend le nom du fichier comme paramètre de constructeur et a une méthode de test qui teste le fichier donné dans le constructeur.

Dans JUnit 4, il pourrait être encore plus facile.

3
répondu Michael Borgwardt 2008-12-11 10:16:57

vous pourriez envisager d'utiliser Bibliothèque JUnitParams , de sorte que vous auriez un peu plus d'options (plus propre):

@org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {

    @org.junit.Test
    @junitparams.Parameters(method = "data")
    public void test1(File file) throws Exception {  }

    @org.junit.Test
    @junitparams.Parameters(method = "data")
    public void test2(File file) throws Exception {  }

    public static File[] data() {
        return new File[] { new File("path1"), new File("path2") };
    }
}

@org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {

    @org.junit.Test
    @junitparams.Parameters(value = { "path1", "path2" })
    public void test1(String path) throws Exception {
        File file = new File(path);
    }

    @org.junit.Test
    @junitparams.Parameters(value = { "path1", "path2" })
    public void test2(String path) throws Exception {
        File file = new File(path);
    }
}

vous pouvez en voir plus exemples d'utilisation ici .

en outre à propos de JUnitParams, pourquoi écrire des tests paramétrisés avec elle est plus facile et plus lisible :

projet JUnitParams ajoute un nouveau coureur à JUnit et fournit beaucoup tests paramétrés plus faciles et lisibles pour JUnit >=4.6.

principales différences par rapport au modèle standard JUnit Parametrised runner:

  • plus explicite - les params sont dans les params de la méthode d'essai, pas dans les champs de classe
  • moins de code-vous n'avez pas besoin d'un constructeur pour configurer les paramètres
  • vous pouvez mélanger paramétrisé avec méthodes non paramétrisées dans une classe
  • params peut être passé comme un CSV de chaîne ou de paramètres à partir d'un fournisseur de classe
  • paramètres du fournisseur de classe peut avoir autant de paramètres fournissant des méthodes que vous le souhaitez, de sorte que vous pouvez regrouper les différents cas
  • vous pouvez avoir une méthode d'essai qui fournit des paramètres (aucune classe externe ou statique plus)
  • vous pouvez voir les valeurs des paramètres réels dans votre IDE (en JUnit est Réglée c'est seulement des nombres consécutifs de paramètres)
2
répondu falsarella 2015-05-20 21:09:28

si TestNG est une option, vous pouvez utiliser les paramètres avec les fournisseurs de données .

le résultat du test de chaque fichier sera affiché dans le rapport textuel ou dans le plugin TestNG UI D'Eclipse. Le nombre total de tests effectués comptera chacun de vos fichiers individuellement.

ce comportement diffère de JUnit théories , dans lequel tous les résultats sont regroupés sous une entrée "théorie" et ne comptent que 1 test. Si vous voulez des rapports de résultat séparés dans JUnit, vous pouvez essayer Parameterized Tests .

entrées

public class FileTest {

    @DataProvider(name="files")
    public File[][] getFiles(){
        return new File[][] {
            { new File("file1") },
            { new File("file2") }
        };
        // or scan a directory
    }

    @Test(dataProvider="files")
    public void testFile(File file){
        //run tests on file
    }
}

exemple de sortie

PASSED: testFile(file1)
PASSED: testFile(file2)

===============================================
    Default test
    Tests run: 2, Failures: 0, Skips: 0
===============================================
1
répondu Ben Hutchison 2014-07-18 20:07:12

j'ai eu un problème similaire et j'ai fini par écrire un JUnit 4 runner simple qui permet à med de générer dynamiquement des tests.

https://github.com/kimble/junit-test-factory

0
répondu Kimble 2016-04-08 19:04:29