Junit4: Exécuter uniquement un test d'une classe avec un coureur paramétré

Créé le 11 avr. 2013  ·  35Commentaires  ·  Source: junit-team/junit4

Lors de l'utilisation du coureur paramétré, il n'est pas possible d'exécuter uniquement une méthode de test d'une classe de test.

Par exemple lors de l'exécution dans maven : mvn test -Dtest=TesClass#testName

Aucun test n'est exécuté lors de l'utilisation du coureur paramétré.

Ce serait formidable d'avoir cette fonctionnalité, car le développement est commun aux développeurs qui essaient d'exécuter uniquement le test sur lequel ils travaillent.

feature parameterized

Commentaire le plus utile

@diogoeag
Avez-vous lu ce chapitre dans Surefire ?
http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html#Multiple_Formats_in_One

Le filtrage des tests paramétrés fonctionne depuis la version 2.19 . Dans votre cas, c'est -Dtest=TesClass#testName[*] au lieu de -Dtest=TesClass#testName .

Tous les 35 commentaires

Corriger cela serait génial, nous finissons par devoir commenter les UT dans les grandes classes de test, ce qui n'est pas souhaitable.

Le plugin Maven Surefire permet de spécifier des globs (voir http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html). Avez-vous essayé cela?

Oui, c'est comme ça que nous aimerions l'utiliser, mais cela ne fonctionne pas. Êtes-vous en train de dire qu'il s'agit d'un problème du plugin surefire et non de junit?

@diogoeag Je pense que c'est un problème avec le plugin Surefire. Vous pouvez vérifier cela en écrivant une classe avec une méthode principale qui utilise JUnitCore pour exécuter les tests d'une classe qui utilisait @Parameterized et demander à votre méthode principale d'appliquer un filtre pour sélectionner l'un des tests

Salut Kevin,

Jetez un œil à ces deux exemples :

Premier test sans paramétré :

package org;

import org.junit.Test;
import org.junit.internal.requests.FilterRequest;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.manipulation.Filter;

public class NoParameterTest {

    public static void main(String[] args) {
        new JUnitCore().run(FilterRequest.aClass(NoParameterTest.class).filterWith(new Filter() {
            <strong i="8">@Override</strong>
            public boolean shouldRun(Description description) {
                System.out.println("Should run test: classname[" + description.getClassName() + "] method name[" + description.getMethodName() + "]");
                return description != null && description.getMethodName() != null && description.getMethodName().equals("test");
            }

            <strong i="9">@Override</strong>
            public String describe() {
                return null;
            }
        }).getRunner());

    }

    <strong i="10">@Test</strong>
    public void test() {
        System.out.println("Running Test: test");
    }

    <strong i="11">@Test</strong>
    public void test2() {
        System.out.println("Running Test: test2");
    }
}

sortir

Should run test: classname[org.NoParameterTest] method name[test]
Should run test: classname[org.NoParameterTest] method name[test2]
Running Test: test

Deuxième test avec paramétré :

package org;

import org.junit.Test;
import org.junit.internal.requests.FilterRequest;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.RunWith;
import org.junit.runner.manipulation.Filter;
import org.junit.runners.Parameterized;

import java.util.Arrays;
import java.util.Collection;

@RunWith(Parameterized.class)
public class ParameterTest {

    public static void main(String[] args) {
        new JUnitCore().run(FilterRequest.aClass(ParameterTest.class).filterWith(new Filter() {
            <strong i="18">@Override</strong>
            public boolean shouldRun(Description description) {
                System.out.println("Should run test: classname[" + description.getClassName() + "] method name[" + description.getMethodName() + "]");
                return description != null && description.getMethodName() != null && description.getMethodName().equals("test");
            }

            <strong i="19">@Override</strong>
            public String describe() {
                return null;
            }
        }).getRunner());

    }


    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[]{"Paramter 1"}, new Object[]{"Parameter 2"});
    }

    private String localParameter;

    public ParameterTest(String parameter) {

        this.localParameter = parameter;
    }

    <strong i="20">@Test</strong>
    public void test() {
        System.out.println("Running Test: test");
        System.out.println("Parameter: " + localParameter);
    }

    <strong i="21">@Test</strong>
    public void test2() {
        System.out.println("Running Test: test2");
        System.out.println("Parameter: " + localParameter);
    }
}

sortir

Should run test: classname[[0]] method name[null]
Should run test: classname[[1]] method name[null]

La description passée au filtre par le paramétré n'est pas correcte, n'est-ce pas ?

@diogoeag Merci pour l'exemple de code. Sur quelle version de JUnit as-tu essayé ? Je pense que nous avons corrigé un problème connexe dans 4.12 mais je ne suis pas sûr.

@kcooney , j'ai testé avec le master actuel 4.12-SNAPSHOT et aussi avec 4.11. Les deux ont le même problème.

Merci. La résolution de ce problème nécessiterait des modifications qui ne sont pas rétrocompatibles. Définir le jalon sur 5,0

Juste pour clarifier, pour résoudre ce problème, il suffirait d'aller dans BlockJUnit4ClassRunnerWithParameters et de supprimer le remplacement de la méthode #testName. Cela remplace la valeur par défaut

    protected String testName(FrameworkMethod method) {
        return method.getName();
    }

par

    <strong i="9">@Override</strong>
    protected String testName(FrameworkMethod method) {
        return method.getName() + getName();
    }

Et les conséquences seraient que le rapport des tests n'aurait pas le nom du paramètre dans le testHeader (au moins les tests qui ont échoué n'étaient que ceux-ci) ?

@diogoeag mais ne voudrions-nous pas le nom du paramètre dans la description ?

Je pense que les correctifs seraient mieux apportés au-dessus du générateur de descriptions sur lequel nous travaillons pour JUnit 5.0.

@kcooney Oui, pour être correct, nous devrions avoir le nom du paramètre dans la description, mais la description ne devrait pas affecter le nom du test. Je suis d'accord avec vous que la description doit avoir un nom de test qui doit être le nom correct et le nom d'affichage qui doit être utilisé dans les descriptions destinées aux utilisateurs et inclure le paramètre.

Avez-vous des estimations sur la date cible à 5.0 ?

Je cherchais les utilisations de getDisplayName pour soumettre une pull request à 5.0 avec le correctif, mais il est utilisé 23 fois dans le projet (sources et tests) et je n'ai pas suffisamment de connaissances sur la source JUnit pour effectuer un tel changement. En attendant, je vais faire un fork pour mon usage personnel avec ce correctif intermédiaire pour moi. Avoir les noms des paramètres n'est pas critique, mais nous permettre d'exécuter des tests uniques nous fait gagner de nombreuses heures dans de nombreux développeurs exécutant des tests dans notre source.

Merci

Si quelqu'un a besoin d'avoir accès à ce correctif temporaire : https://github.com/feedzai/junit/commit/be41d2980227d86915d9c8b6f800070a0ef1ff7a

@diogoeag
Regarde ça. Cela aiderait-il infailliblement 2.18 ?
https://github.com/apache/maven-surefire/pull/46

@ Tibor17 Je ne suis pas sûr. Parce que shoudlRun utilisera également la description. Je ne connais pas assez la base de code pour savoir si cela fonctionnera. Seulement le tester. Mon exemple de code peut également être l'un des tests pour votre correctif. L'utilisation de tests paramétrés pose le problème de changer le nom du test.

@diogoeag
Dans surefire MethodFilter, vous devriez pouvoir spécifier une condition comme celle-ci :

String filterBy = JunitVersion < 5.0 & <strong i="7">@RunWith</strong> = Parameterized.class ? methodName + className : methodName

Si vous souhaitez tolérer les problèmes JUnit, vous pouvez valider vous-même le correctif dans le projet Maven Surefire.

@diogoeag nous n'avons pas encore de date cible pour JUnit 5.0, mais ce serait probablement la sortie après 4.12. Nous nous concentrons actuellement sur la sortie de la 4.12

@kcooney merci. Nous utiliserons notre version interne en attendant.

Bonjour, qu'en est-il de ce problème ? Existe-t-il une solution de contournement pour utiliser Parameterized.class et avoir la possibilité d'exécuter un seul test à l'aide de maven surefire ? Ou devons-nous attendre la version 5.0 pour cela ?

@Fanch- il n'y a pas de correctif actuel. Nous pensions que cela résoudrait également le problème du travail sur ImmutableDescription sur lequel nous travaillions, mais cet effort a été abandonné.

screen shot 2016-11-16 at 17 42 48

Je pense qu'il serait acceptable de supprimer getName() de testName() car c'est de toute façon redondant.

@junit-team/junit-committers Qu'en pensez-vous ?

Tant que toutes les instances Description sont uniques pour un test partameterized.

Nous pourrions définir l'ID unique dans la description pour les rendre uniques. Cependant, je me demande si/pourquoi ils doivent être uniques dans tout le sous-arbre ?

Oui, les instances Description doivent être uniques. C'est tout ce qui est transmis à l'auditeur pour référencer un début et une fin de test. Pour créer un arbre comme vous l'avez montré et le mettre à jour pendant le test, vous devez savoir quel test a démarré.

Point pris. Donc, je pense que nous devrions ajouter une nouvelle méthode d'usine à Description qui crée une description de test avec un ID unique explicite. Nous pourrions ensuite passer le nom actuel en tant qu'ID unique et utiliser uniquement le nom de la méthode comme nom d'affichage. Qu'est-ce que tu penses?

@marcphilipp il existe déjà une méthode dans Description pour créer une description de test avec un ID unique donné : https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runner/ Description.java#L109

Je ne pense pas que Description devrait _générer_ des identifiants uniques. Parameterized ne pourrait-il pas passer une valeur déterministe à Description.createTestDescription() ?

il existe déjà une méthode dans Description pour créer une description de test avec un ID unique donné : https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runner/Description. java#L109

Oui, mais celui-là n'a pas de paramètre de classe. Nous avons donc besoin d'un autre.

Je ne pense pas que Description devrait _générer_ des identifiants uniques. Parameterized ne pourrait-il pas passer une valeur déterministe à Description.createTestDescription() ?

Je ne voulais pas dire ça. Je voulais dire que Parameterized devrait _passer_ method.getName() + getName() comme identifiant unique et method.getName() comme nom.

SGTM.

Même si nous avons abandonné l'idée d'avoir des instances de description immuables pour JUnit 4, devrions-nous ajouter un constructeur pour éviter d'avoir autant de méthodes de création statiques ?

Sûr! ??

Y a-t-il des estimations quand il sera corrigé ?
Ce bogue bloque le bogue lié de JUnit5
https://github.com/junit-team/junit5/issues/549

@SqAutoTestTeam personne ne travaille activement là-dessus. J'ai récemment mis à jour la branche du générateur de description afin qu'un contributeur ambitieux puisse commencer à partir de là. Alternativement, nous pourrions ajouter encore une autre méthode statique à Description .

Corriger cela nécessiterait de nouvelles API sur Description. Nous ne voudrions pas que JUnit 5 nécessite ces nouvelles API (actuellement JUnit 5 fonctionnerait sur à peu près n'importe quelle version de JUnit 4.x)

@diogoeag
Avez-vous lu ce chapitre dans Surefire ?
http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html#Multiple_Formats_in_One

Le filtrage des tests paramétrés fonctionne depuis la version 2.19 . Dans votre cas, c'est -Dtest=TesClass#testName[*] au lieu de -Dtest=TesClass#testName .

@kcooney et @marcphilipp ,

Que pensez-vous du "backportage" du _fix_ dans https://github.com/junit-team/junit5/pull/1018/files#diff -42ed8b618527eb1521dbe3cd9100e949R48 vers JUnit 4 ?

@sbrannen qui ressemble à un changement raisonnable. Je voudrais juste m'assurer que si nous rétroportions ces modifications, nous ne rendrions pas JUnit 4.13 incompatible avec JUnit 5, ou n'exigerions pas que les projets avec des tests de style JUnit 4 passent à la version 4.13 avant de pouvoir exécuter leurs tests de style JUnit 4 à l'aide du API d'exécution JUnit 5.

@kcooney ,

cela ressemble à un changement raisonnable.

??

Je voudrais juste m'assurer que si nous rétroportions ces modifications, nous ne rendrions pas JUnit 4.13 incompatible avec JUnit 5, ou n'exigerions pas que les projets avec des tests de style JUnit 4 passent à la version 4.13 avant de pouvoir exécuter leurs tests de style JUnit 4 à l'aide du API d'exécution JUnit 5.

Dans JUnit 4, le changement ne concernerait qu'une seule ligne dans Filter#matchMethodDescription(Description) , et nous pouvons conserver le même _fix_ dans JUnit Vintage qu'aujourd'hui afin que le VintageTestEngine continue à fonctionner avec JUnit 4.12 .

Donc, à moins que j'oublie quelque chose, cela devrait éviter tout problème de compatibilité.

Qu'est-ce que tu penses?

@sbrannen SGTM

Cette page vous a été utile?
0 / 5 - 0 notes