Junit: test d’intégration et tests unitaires

J’ai hérité d’une charge de test Junit, mais ces tests (hormis ceux qui ne fonctionnent pas) sont un mélange de tests unitaires réels et de tests d’intégration (nécessitant des systèmes externes, db, etc.).

J’essaie donc de penser à un moyen de les séparer, de sorte que je puisse exécuter le test unitaire rapidement et que les tests d’intégration soient terminés.

Les options sont ..

  1. Divisez-les en répertoires distincts.

  2. Passez à Junit4 (à partir de v3) et annotez les classes pour les séparer.

  3. Utilisez une convention de dénomination de fichier pour indiquer ce qu’est une classe, à savoir AdapterATest et AdapterAIntergrationTest.

3 a le problème que Eclipse a l’option “Exécuter tous les tests dans le projet / package ou dossier sélectionné”. Il serait donc très difficile de simplement exécuter les tests d’intégration.

2: risque que les développeurs commencent à écrire des tests d’intégration dans des classes de tests unitaires et que cela ne soit que salissant.

1: Cela semble être la solution la plus efficace, mais mon intestin dit qu’il doit y avoir une meilleure solution.

Voilà donc ma question: comment séparez-vous les tests d’intégration et les tests unitaires appropriés?

J’utilise actuellement des répertoires distincts en raison de la politique de l’organisation (et de l’inheritance de Junit 3), mais je souhaite passer aux annotations moi-même maintenant que je suis sur Junit 4.

Je ne serais pas trop préoccupé par le fait que les développeurs mettent des tests d’intégration dans vos classes de tests unitaires – ajoutez une règle dans vos normes de codage si nécessaire.

Je suis intéressé de savoir quel autre type de solutions il pourrait y avoir en dehors des annotations ou de la séparation physique des classes.

Vous pouvez les diviser très facilement en utilisant les catégories JUnit et Maven.

Ceci est montré très, très brièvement ci-dessous en séparant les tests unitaires et d’intégration.

Définir une interface de marqueur

La première étape du regroupement d’un test utilisant des catégories consiste à créer une interface de marqueur.

Cette interface sera utilisée pour marquer tous les tests que vous souhaitez exécuter en tant que tests d’intégration.

public interface IntegrationTest {} 

Marquez vos classes de test

Ajoutez l’annotation de la catégorie en haut de votre classe de test. Il prend le nom de votre nouvelle interface.

 import org.junit.experimental.categories.Category; @Category(IntegrationTest.class) public class ExampleIntegrationTest{ @Test public void longRunningServiceTest() throws Exception { } } 

Configurer les tests d’unité Maven

La beauté de cette solution est que rien ne change vraiment pour le côté des tests unitaires.

Nous ajoutons simplement une configuration au plug-in maven surefire pour l’ignorer tous les tests d’intégration.

  org.apache.maven.plugins maven-surefire-plugin 2.11   org.apache.maven.surefire surefire-junit47 2.12     **/*.class  com.test.annotation.type.IntegrationTest   

Lorsque vous effectuez un test de nettoyage mvn, seuls vos tests unitaires non marqués seront exécutés.

Configurer les tests d’intégration Maven

Encore une fois, la configuration est très simple.

Pour exécuter uniquement les tests d’intégration, utilisez ceci:

  org.apache.maven.plugins maven-surefire-plugin 2.11   org.apache.maven.surefire surefire-junit47 2.12    com.test.annotation.type.IntegrationTest   

Si vous encapsulez cela dans un profil avec id IT , vous ne pouvez exécuter que les tests rapides en utilisant mvn clean install . Pour exécuter uniquement les tests d’intégration / lents, utilisez mvn clean install -P IT .

Mais le plus souvent, vous voudrez exécuter les tests rapides par défaut et tous les tests avec -P IT . Si c’est le cas, alors vous devez utiliser une astuce:

   IT    org.apache.maven.plugins maven-surefire-plugin  java.io.Serializable        

Comme vous pouvez le constater, j’exclus les tests annotés avec java.io.Serializable . Cela est nécessaire car le profil héritera de la configuration par défaut du plug-in Surefire. Par conséquent, même si vous dites ou , la valeur com.test.annotation.type.IntegrationTest sera utilisée.

Vous ne pouvez pas non plus en utiliser, car il doit s’agir d’une interface sur le classpath (Maven vérifiera cela).

Remarques:

  • La dépendance à surefire-junit47 n’est nécessaire que lorsque Maven ne bascule pas automatiquement vers le runner JUnit 4. L’utilisation de l’élément groups ou excludedGroups doit déclencher le commutateur. Voir ici
  • La plupart du code ci-dessus provient de la documentation du plug-in Maven Failsafe. Voir la section “Utilisation des catégories JUnit” sur cette page .
  • Lors de mes tests, j’ai constaté que cela fonctionne même lorsque vous utilisez les annotations @RunWith() pour exécuter des suites ou des tests basés sur Spring.

Nous utilisons Maven Surefire Plugin pour exécuter des tests unitaires et Maven Failsafe Plugin pour exécuter des tests d’intégration. Les tests unitaires suivent les conventions de nommage **/Test*.java **/*Test.java **/*TestCase.java , tests d’intégration – **/IT*.java **/*IT.java **/*ITCase.java . C’est donc en fait votre option numéro trois.

Dans quelques projets, nous utilisons TestNG et définissons différents groupes de tests pour les tests d’intégration / unité, mais cela ne vous convient probablement pas.

Je passerais à Junit4 juste pour l’avoir 🙂

Vous pouvez les séparer en différentes suites de tests. Je ne sais pas comment ils sont organisés dans Junit3, mais il devrait être facile dans Junit4 de construire des suites de tests et de mettre tous les tests unitaires réels dans une d’entre elles, puis d’utiliser une deuxième suite pour les tests d’intégration.

Définissez maintenant une configuration d’exécution pour les deux suites dans eclipse et vous pouvez facilement exécuter une seule suite. Ces suites pourraient également être lancées à partir d’un processus automatisé vous permettant d’exécuter les tests unitaires chaque fois que la source change et peut-être les tests d’intégration (s’ils sont vraiment volumineux) une fois par jour ou une fois par heure.

L’ utilisation de l’annotation de spring IfProfileValue permet d’y parvenir sans qu’un plugin ou une configuration maven ne soit requirejs.

Annoter les classes ou les méthodes de test d’intégration à l’aide de IfProfileValue

 import org.springframework.test.annotation.IfProfileValue; @IfProfileValue(name="test-groups", value="integration") public class ExampleIntegrationTest{ @Test public void longRunningServiceTest() throws Exception { } } 

Pour exécuter en utilisant des tests unitaires uniquement:

 mvn clean test 

Pour exécuter en utilisant des tests d’intégration et des tests unitaires:

 mvn clean test -Dtest-groups=integration 

En outre, “Exécuter tout le test” dans un IDE exécutera uniquement le test unitaire. Ajoutez -Dtest-groups=integration aux arguments de la VM pour exécuter les tests d’intégration et les tests unitaires.

Il n’y a pas une bonne réponse. Comme vous l’avez expliqué, il y a plusieurs façons de le faire qui fonctionneront. J’ai fait le schéma de nommage des fichiers et divisé les choses en différents répertoires.

Il semblerait que diviser quelque chose en différents répertoires fonctionne mieux pour vous, et cela me semble un peu plus clair.

Je ne pense pas que j’essaierais des annotations parce que cela me semble plus fin. Voulez-vous vraiment que ces deux types de tests soient mélangés dans le même fichier? Je ne le ferais pas