web-dev-qa-db-fra.com

Regroupement des tests JUnit

Existe-t-il un moyen de regrouper des tests dans JUnit, afin que je ne puisse exécuter que certains groupes?

Ou est-il possible d'annoter certains tests et de les désactiver globalement?

J'utilise JUnit 4 , je ne peux pas utiliser TestNG.

edit: @RunWith et @SuiteClasses fonctionnent très bien. Mais est-il possible d'annoter comme ceci seulement quelques tests en classe de test? Ou dois-je annoter toute la classe de test?

39
Jakub Arnold

Voulez-vous grouper des tests dans une classe de test ou voulez-vous grouper des classes de test? Je vais assumer ce dernier.

Cela dépend de la façon dont vous exécutez vos tests. Si vous les exécutez avec Maven, il est possible de spécifier exactement quels tests vous souhaitez inclure. Voir la documentation sur Maven surefire pour cela.

Plus généralement, cependant, ce que je fais, c’est que j’ai un arbre de suites de tests. Une suite de tests dans JUnit 4 ressemble à quelque chose comme:

 @RunWith(Suite.class)
 @SuiteClasses(SomeUnitTest1.class, SomeUnitTest2.class)
 public class UnitTestsSuite {
 }

Donc, j'ai peut-être un FunctionTestsSuite et un UnitTestsSuite, puis un AllTestsSuite qui inclut les deux autres. Si vous les exécutez dans Eclipse, vous obtenez une très belle vue hiérarchique.

Le problème avec cette approche est que c'est un peu fastidieux si vous voulez découper des tests de plusieurs manières différentes. Mais c'est toujours possible (vous pouvez par exemple avoir un ensemble de suites qui tranche en fonction du module, puis un autre en fonction du type de test).

8
waxwing

JUnit 4.8 prend en charge le regroupement:

public interface SlowTests {}
public interface IntegrationTests extends SlowTests {}
public interface PerformanceTests extends SlowTests {}

Et alors...

public class AccountTest {

    @Test
    @Category(IntegrationTests.class)
    public void thisTestWillTakeSomeTime() {
        ...
    }

    @Test
    @Category(IntegrationTests.class)
    public void thisTestWillTakeEvenLonger() {
        ...
    }

    @Test
    public void thisOneIsRealFast() {
        ...
    }
}

Et enfin,

@RunWith(Categories.class)
@ExcludeCategory(SlowTests.class)
@SuiteClasses( { AccountTest.class, ClientTest.class })
public class UnitTestSuite {}

Tiré d'ici: http://weblogs.Java.net/blog/johnsmart/archive/2010/04/25/grouping-tests-using-junit-categories-0

De plus, Arquillian lui-même supporte le regroupement: https://github.com/weld/core/blob/master/tests-arquillian/src/test/Java/org/jboss/weld/tests/Categories.Java

73
Ondra Žižka

Pour gérer leur désactivation globale, JUnit (4.5+) dispose de deux méthodes. L'une consiste à utiliser la nouvelle méthode supposeThat. Si vous mettez cela dans la classe @BeforeClass (ou la classe @Avant) d'une classe de test et si la condition échoue, le test sera ignoré. Dans ces conditions, vous pouvez définir une propriété système ou autre chose pouvant être activée ou désactivée de manière globale.

L'autre alternative consiste à créer un coureur personnalisé qui comprend la propriété globale et les délègue au coureur approprié. Cette approche est beaucoup plus fragile (car les coureurs internes de JUnit4 sont instables et peuvent être changés d’une édition à l’autre), mais elle présente l’avantage de pouvoir être héritée dans une hiérarchie de classes et remplacée dans une sous-classe. C'est également le seul moyen réaliste de le faire si vous devez prendre en charge les anciennes classes JUnit38.

Voici un code pour faire le Runner personnalisé. Concernant ce que pourrait faire getAppropriateRunnerForClass, je l’ai implémenté de manière à avoir une annotation distincte qui indique au coureur personnalisé avec quoi exécuter. La seule alternative était un copier-coller très fragile du code JUnit.

private class CustomRunner implements Runner
 private Runner runner;

    public CustomRunner(Class<?> klass, RunnerBuilder builder) throws Throwable {
        if (!isRunCustomTests()) {
            runner = new IgnoredClassRunner(klass);
        } else {
            runner = getAppropriateRunnerForClass(klass, builder);
    }

    public Description getDescription() {
        return runner.getDescription();
    }

    public void run(RunNotifier notifier) {
        runner.run(notifier);
    }
}

EDIT: La balise @RunWith ne fonctionne que pour une classe entière. Une façon de contourner cette limitation consiste à déplacer les méthodes de test dans une classe interne statique et à les annoter. De cette façon, vous avez l'avantage de l'annotation avec l'organisation de la classe. Mais cela ne vous aidera pas avec les balises @Before ou @BeforeClass, vous devrez les recréer dans la classe interne. Il peut appeler la méthode de la classe externe, mais il devrait avoir sa propre méthode en tant que hook.

9
Yishai

Essayez Groupes de tests JUnit . De la documentation:

@TestGroup("integration")
public class MyIntegrationTest {
   @ClassRule
   public static TestGroupRule rule = new TestGroupRule();

   ...
}
  • Exécuter un groupe de test simple: -Dtestgroup = integration
  • Exécutez plusieurs groupes de tests: -Dtestgroup = group1, group2
  • Exécutez tous les groupes de tests: -Dtestgroup = all
3
Bit-Man

Vous pouvez créer des objets test Suite contenant des groupes de tests. Sinon, votre IDE (comme Eclipse) peut prendre en charge l'exécution de tous les tests contenus dans un package donné.

1
Kevin

Dans JUnit 5, vous pouvez déclarer @Tag pour les tests de filtrage, au niveau de la classe ou de la méthode; analogue aux groupes de test dans TestNG ou aux catégories dans JUnit 4

De la javadoc

les balises sont utilisées pour filtrer quels tests sont exécutés pour un test donné plan. Par exemple, une équipe de développement peut baliser les tests avec des valeurs telles que comme "rapide", "lent", "ci-serveur", etc. et ensuite fournir une liste de balises à être utilisé pour le plan de test actuel, potentiellement dépendant du fichier environnement actuel.

Par exemple, vous pouvez déclarer une classe de test avec un "slow"@Tag qui sera hérité pour toutes les méthodes et la remplacer pour certaines méthodes si nécessaire:

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Tag("slow") 
public class FooTest{

   // 
   @Test
   void loadManyThings(){ 
        ...
   }

   @Test
   void loadManyManyThings(){ 
        ...
   }


   @Test
   @Tag("fast")
   void loadFewThings(){ 
        ...
   }

}

Vous pouvez appliquer la même logique pour d'autres classes de test.
De cette manière, les classes de test (ainsi que les méthodes) appartiennent à une balise spécifique. 

En guise de bonne pratique, au lieu de copier-coller @Tag("fast") et @Tag("slow") dans les classes de test, vous pouvez créer des annotations composées personnalisées.
Par exemple : 

import Java.lang.annotation.ElementType;
import Java.lang.annotation.Retention;
import Java.lang.annotation.RetentionPolicy;
import Java.lang.annotation.Target;

import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("slow")
public @interface Fast {
}

et l'utiliser comme:

@Test
@Slow
void slowProcessing(){ 
    ...
}   

Pour activer ou désactiver le test marqué avec une balise spécifique lors de l'exécution du texte, vous pouvez vous fier à la documentation maven-surefire-plugin :

Pour inclure des balises ou des expressions de balises, utilisez groups.

Pour exclure des balises ou des expressions de balises, utilisez soit excludedGroups.

Configurez simplement le plugin dans votre pom.xml selon vos besoins (exemple de la doc):

 <build>
     <plugins>
         ...
         <plugin>
             <groupId>org.Apache.maven.plugins</groupId>
             <artifactId>maven-surefire-plugin</artifactId>
             <version>2.22.0</version>
             <configuration>
                 <groups>acceptance | !feature-a</groups>
                 <excludedGroups>integration, regression</excludedGroups>
             </configuration>
         </plugin>
     </plugins> 
</build> 

Pour information, la documentation de l'objectif test n'est pas mise à jour. 

1
davidxxx

Vous pouvez utiliser Test Suite ( http://qaautomated.blogspot.in/2016/09/junit-test-suits-and-test-execution.html ) ou vous pouvez créer des catégories Junit ( http: // qaautomated.blogspot.in/2016/09/junit-categories.html ) pour regrouper efficacement vos cas de test.

0
anuja jain