Couverture de code par les tests en Java : outils et métriques en pratique
\n\nAvez-vous déjà eu l'impression d'être le capitaine d'un navire convaincu que son bateau est insubmersible, sans jamais avoir vérifié la coque pour des voies d'eau ? C'est à peu près la même chose que le développement Java sans analyse de la couverture de code par les tests. Vous écrivez des tests, mais vous ne savez pas à quel point ils protègent réellement votre projet des bogues. Dans cet article, nous allons voir ce qu'est la couverture de code par les tests en Java, quels outils de couverture de code aident vraiment à ne pas sombrer dans les régressions, et comment lire correctement les métriques pour ne pas se leurrer.
\n\nPourquoi "écrire des tests" ne suffit-il pas ?
\nDe nombreux développeurs pensent : "J'ai écrit 50 tests, donc mon projet est protégé". Mais le nombre de tests n'est pas égal à la qualité. Sans métriques, vous risquez de :
\n- \n
- Passer à côté de branches entières de logique (par exemple, la gestion des exceptions) ; \n
- Tester uniquement les "chemins heureux", en ignorant les cas limites ; \n
- Perdre du temps sur des tests qui ne vérifient pas le nouveau code. \n
C'est là que la code coverage Java entre en jeu — une évaluation objective du pourcentage de code source exécuté pendant les tests. Ce n'est pas une panacée, mais une boussole puissante pour l'équipe.
\n\nLes principales métriques de couverture de code en Java
\nAvant de choisir un outil, voyons ce que nous mesurons exactement. Dans le monde Java, on distingue quatre métriques clés :
\n\n1. Couverture de lignes (Line Coverage)
\nLa métrique la plus simple : combien de lignes de code ont été exécutées au moins une fois. Si une ligne n'est pas exécutée, cela signifie que personne ne l'a testée. Exemple :
\npublic int divide(int a, int b) {\n if (b == 0) {\n throw new IllegalArgumentException("Division by zero"); // Ligne 3\n }\n return a / b; // Ligne 5\n}\nSi votre test appelle divide(10, 2), la ligne 3 restera non couverte. La couverture de lignes Java affichera 50%.
2. Couverture de branches (Branch Coverage)
\nCette métrique est plus subtile. Elle vérifie si tous les chemins logiques (if-else, switch, opérateurs ternaires) ont été parcourus. Pour la même méthode divide :
- \n
- Branche 1 : b == 0 (true) — levée d'exception ; \n
- Branche 2 : b != 0 (false) — division. \n
Si vous n'avez testé que la division, la couverture de branches sera de 50%. Et si vous ajoutez un test avec b=0, elle passera à 100%.
\n\n3. Couverture de conditions (Condition Coverage)
\nUne métrique plus approfondie qui examine chaque sous-condition dans les expressions complexes. Par exemple, dans le code if (a > 0 && b < 10), il faut vérifier 4 combinaisons : (true, true), (true, false), (false, true), (false, false).
4. Couverture de mutations (Mutation Coverage)
\nL'étalon-or. L'outil (par exemple, PIT) apporte de petites modifications au code — change >= en <, supprime un appel de méthode — et vérifie si au moins un test échoue. Si le test ne tombe pas, cela signifie qu'il n'est pas assez sensible. Les tests de mutation Java sont la meilleure façon d'évaluer la qualité des tests, mais c'est plus lent.
Les meilleurs outils de couverture de code pour Java
\nLe marché propose plusieurs solutions matures. Examinons les plus populaires.
\n\nJaCoCo — la norme de l'industrie
\nJaCoCo (Java Code Coverage) est une bibliothèque open-source qui s'intègre dans la construction (Maven, Gradle) et génère des rapports en HTML, XML ou CSV. Il prend en charge toutes les métriques principales, à l'exception des mutations.
\nExemple de configuration dans Maven (pom.xml) :
\n<plugin>\n <groupId>org.jacoco</groupId>\n <artifactId>jacoco-maven-plugin</artifactId>\n <version>0.8.11</version>\n <executions>\n <execution>\n <goals>\n <goal>prepare-agent</goal>\n </goals>\n </execution>\n <execution>\n