web-dev-qa-db-fra.com

Test JUnit avec nombre dynamique de tests

Dans notre projet, j'ai plusieurs JUnit tests qui par exemple prenez chaque fichier d'un répertoire et lancez un test dessus. Si j'implémente 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 de chaque dossier individuel. Comment puis-je écrire un TestCase/TestSuite de telle sorte que chaque fichier s'affiche comme un test séparé, par exemple dans le TestRunner graphique d'Eclipse? (Le codage d'une méthode de test explicite pour chaque fichier n'est pas une option.)

Comparez également la question ParameterizedTest avec un nom dans Eclipse Testrunner .

92
Hans-Peter Störr

Jetez un œil à Tests paramétrés dans JUnit 4.

En fait, je l'ai fait il y a quelques jours. Je vais essayer d'expliquer ...

Commencez par créer votre classe de test normalement, car vous n'étiez qu'à tester avec un seul fichier d'entrée. Décorez votre classe avec:

@RunWith(Parameterized.class)

Construisez un constructeur qui prend l'entrée qui changera à chaque appel de test (dans ce cas, il peut s'agir du fichier lui-même)

Ensuite, créez une méthode statique qui renverra 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écorez 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;
    }
}

Vérifiez également ceci exemple

99
bruno conde

JUnit

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
McDowell

Junit 5 Tests paramétrés

JUnit 5 les tests paramétrés supportent cela 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 prend également cela en charge par la notion d'un DynamicTest, qui doit être généré dans un @TestFactory, au 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 exécutés dans votre IDE (IntelliJ ici) seront affichés comme ceci:

Output in IntelliJ

9
avandeursen

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

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

3
Michael Borgwardt

Vous pourriez envisager d'utiliser bibliothèque JUnitParams , vous auriez donc quelques options (plus propres):

@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 voir plus exemples d'utilisation ici .

De plus à propos de JUnitParams, pourquoi écrire des tests paramétrés avec est plus facile et plus lisible :

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

Principales différences par rapport au runner paramétré JUnit standard:

  • plus explicite - les paramètres sont dans les paramètres de la méthode de test, pas les champs de classe
  • moins de code - vous n'avez pas besoin d'un constructeur pour configurer les paramètres
  • vous pouvez mélanger des méthodes paramétrées avec des méthodes non paramétrées dans une classe
  • les paramètres peuvent être passés sous forme de chaîne CSV ou à partir d'une classe de fournisseur de paramètres
  • la classe de fournisseur de paramètres peut avoir autant de paramètres fournissant des méthodes que vous le souhaitez, afin que vous puissiez regrouper différents cas
  • vous pouvez avoir une méthode de test qui fournit des paramètres (plus de classes externes ou statiques)
  • vous pouvez voir les valeurs réelles des paramètres dans votre IDE (dans Parametrised de JUnit, ce ne sont que des nombres consécutifs de paramètres)
2
falsarella

Si TestNG est une option, vous pouvez utiliser Paramètres avec DataProviders .

Le test de chaque fichier individuel aura son résultat affiché dans le rapport texte ou l'interface utilisateur du plugin TestNG d'Eclipse. Le nombre total de tests exécutés comptera chacun de vos fichiers individuellement.

Ce comportement diffère de JUnit Theories , dans lequel tous les résultats sont regroupés sous une entrée "théorique" et ne comptent que pour 1 test. Si vous voulez des rapports de résultats séparés dans JUnit, vous pouvez essayer Tests paramétrés .

Test et 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
Ben Hutchison

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

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

0
Kimble