Introduction à JaCoCo

1. Vue d'ensemble

La couverture de code est une métrique logicielle utilisée pour mesurer le nombre de lignes de notre code exécutées lors de tests automatisés.

Dans cet article, nous allons parcourir quelques aspects pratiques de l'utilisation de JaCoCo - un générateur de rapports de couverture de code pour les projets Java.

2. Configuration Maven

Pour être opérationnel avec JaCoCo, nous devons déclarer ce plugin maven dans notre fichier pom.xml :

 org.jacoco jacoco-maven-plugin 0.7.7.201606060606    prepare-agent    report prepare-package  report     

Le lien fourni ci-dessus vous mènera toujours à la dernière version du plugin dans le référentiel central maven.

3. Rapports de couverture du code

Avant de commencer à examiner les capacités de couverture de code de JaCoCo, nous avons besoin d'un exemple de code. Voici une fonction Java simple qui vérifie si une chaîne lit la même chose en arrière et en avant:

public boolean isPalindrome(String inputString) { if (inputString.length() == 0) { return true; } else { char firstChar = inputString.charAt(0); char lastChar = inputString.charAt(inputString.length() - 1); String mid = inputString.substring(1, inputString.length() - 1); return (firstChar == lastChar) && isPalindrome(mid); } }

Tout ce dont nous avons besoin maintenant est un simple test JUnit :

@Test public void whenEmptyString_thenAccept() { Palindrome palindromeTester = new Palindrome(); assertTrue(palindromeTester.isPalindrome("")); }

L'exécution du test à l'aide de JUnit mettra automatiquement en mouvement l'agent JaCoCo, ainsi, il créera un rapport de couverture au format binaire dans le répertoire cible - target / jacoco.exec.

Évidemment, nous ne pouvons pas interpréter la sortie à lui seul, mais d'autres outils et plugins peuvent le faire - par exemple Sonar Qube .

La bonne nouvelle est que nous pouvons utiliser l' objectif jacoco: report afin de générer des rapports de couverture de code lisibles dans plusieurs formats - par exemple HTML, CSV et XML.

Nous pouvons maintenant jeter un œil par exemple à la page target / site / jacoco / index.html pour voir à quoi ressemble le rapport généré:

En suivant le lien fourni dans le rapport - Palindrome.java , nous pouvons explorer une vue plus détaillée pour chaque classe Java:

Notez que vous pouvez gérer directement la couverture de code en utilisant JaCoCo dans Eclipse sans configuration , grâce au plugin EclEmma Eclipse.

4. Analyse du rapport

Notre rapport montre 21% de couverture des instructions, 17% de couverture des succursales, 3/5 pour la complexité cyclomatique , etc.

Les 38 instructions présentées par JaCoCo dans le rapport se réfèrent aux instructions de bytecode par opposition aux instructions de code Java ordinaires.

Les rapports JaCoCo vous aident à analyser visuellement la couverture du code en utilisant des losanges avec des couleurs pour les branches et des couleurs d'arrière-plan pour les lignes:

  • Le losange rouge signifie qu'aucune branche n'a été exercée pendant la phase de test.
  • Le losange jaune montre que le code est partiellement couvert - certaines branches n'ont pas été exercées.
  • Le losange vert signifie que toutes les branches ont été exercées pendant le test.

Le même code couleur s'applique à la couleur d'arrière-plan, mais pour la couverture des lignes.

JaCoCo fournit principalement trois métriques importantes:

  • La couverture des lignes reflète la quantité de code qui a été exercée en fonction du nombre d'instructions de code d'octet Java appelées par les tests.
  • La couverture des branches indique le pourcentage de branches exercées dans le code - généralement lié aux instructions if / else et switch .
  • La complexité cyclomatique reflète la complexité du code en donnant le nombre de chemins nécessaires pour couvrir tous les chemins possibles dans un code par combinaison linéaire.

Pour prendre un exemple trivial, s'il n'y a pas d' instructions if ou switch dans le code, la complexité cyclomatique sera de 1, car nous n'avons besoin que d'un seul chemin d'exécution pour couvrir tout le code.

En général, la complexité cyclomatique reflète le nombre de cas de test que nous devons implémenter pour couvrir tout le code.

5. Répartition du concept

JaCoCo s'exécute en tant qu'agent Java , il est responsable de l' instrumentation du bytecode lors de l'exécution des tests. JaCoCo explore chaque instruction et montre quelles lignes sont exercées pendant chaque test.

Pour collecter les données de couverture, JaCoCo utilise ASM pour l'instrumentation de code à la volée, recevant des événements de l' interface de l' outil JVM dans le processus:

Il est également possible d'exécuter l'agent JaCoCo en mode serveur, dans ce cas, nous pouvons exécuter nos tests avec jacoco: dump comme objectif, pour lancer une requête de vidage.

Vous pouvez suivre le lien de documentation officiel pour plus de détails sur la conception de JaCoCo.

6. Score de couverture du code

Maintenant que nous en savons un peu plus sur le fonctionnement de JaCoCo, améliorons notre score de couverture de code.

Afin d'atteindre une couverture de code à 100%, nous devons introduire des tests, qui couvrent les parties manquantes indiquées dans le rapport initial:

@Test public void whenPalindrom_thenAccept() { Palindrome palindromeTester = new Palindrome(); assertTrue(palindromeTester.isPalindrome("noon")); } @Test public void whenNearPalindrom_thanReject(){ Palindrome palindromeTester = new Palindrome(); assertFalse(palindromeTester.isPalindrome("neon")); }

Maintenant, nous pouvons dire que nous avons suffisamment de tests pour couvrir tout notre code, mais pour nous en assurer, exécutons la commande Maven mvn jacoco: report pour publier le rapport de couverture:

Comme vous pouvez le voir, toutes les lignes / branches / chemins de notre code sont entièrement couverts:

Dans un projet réel, et à mesure que les développements vont plus loin, nous devons suivre le score de couverture du code.

JaCoCo offre un moyen simple de déclarer les exigences minimales à respecter , sinon la compilation échouera.

Nous pouvons le faire en ajoutant l' objectif de vérification suivant dans notre fichier pom.xml :

 jacoco-check  check     PACKAGE   LINE COVEREDRATIO 0.50      

Comme vous pouvez probablement le deviner, nous limitons ici le score minimum pour la couverture des lignes à 50%.

The jacoco:check goal is bound to verify, so we can run the Maven command – mvn clean verify to check whether the rules are respected or not. The logs will show something like:

[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.7.7.201606060606:check (jacoco-check) on project mutation-testing: Coverage checks have not been met.

7. Conclusion

In this article we've seen how to make use of JaCoCo maven plugin to generate code coverage reports for Java projects.

Keep in mind though, 100% code coverage does not necessary reflects effective testing, as it only reflects the amount of code exercised during tests. In a previous article, we've talked about mutation testing as a more sophisticated way to track tests effectiveness compared to ordinary code coverage.

Vous pouvez consulter l'exemple fourni dans cet article dans le projet GitHub lié .