Couverture de code : comment la mesurer, comprendre les indicateurs et améliorer vos tests, avec Qodana, l'outil d'analyse de la qualité du code de JetBrains

JetBrains est une société à responsabilité limitée internationale spécialisée dans le développement de logiciels, qui conçoit des outils destinés aux développeurs et aux chefs de projet. JetBrains propose divers environnements de développement intégrés (EDI), tels que IntelliJ IDEA, PyCharm, WebStorm et CLion. Elle a également créé en 2011 le langage de programmation Kotlin, qui peut s'exécuter dans une machine virtuelle Java (JVM).

Qodana est un outil d'analyse de la qualité du code qui utilise l'analyse statique pour aider les utilisateurs à réaliser des revues de code, à mettre en place des contrôles de qualité et à appliquer les directives relatives à la qualité du code. Lancé officiellement en juillet 2023, il est compatible avec les EDI de l'écosystème JetBrains, s'intègre aux pipelines CI/CD et prend en charge l'analyse de code dans plus de 60 langages de programmation.

La couverture de code (Code coverage) fait partie de ces indicateurs dont toutes les équipes de développement parlent, mais que peu exploitent pleinement. Que vous lanciez un produit SaaS ou que vous assuriez la maintenance d’une application monolithique héritée, comprendre ce que vos tests couvrent réellement – et ce qu’ils laissent de côté – peut faire la différence entre une mise en production en toute confiance et une alerte d’incident à 2 heures du matin.

Cet article vous présente les indicateurs de couverture essentiels, vous explique comment les mesurer à l’aide d’outils modernes et vous propose des mesures concrètes pour améliorer la couverture de code sans gaspiller d’efforts sur des tests inutiles. Les rapports de couverture de code sont disponibles avec les licences Qodana Ultimate et Qodana Ultimate Plus. Pour en savoir plus sur les licences Qodana disponibles, consultez la page Options d’abonnement et tarifs. Vous pouvez également demander une démonstration.

Nom : 0.jpg
Affichages : 3271
Taille : 28,2 Ko

En bref

- La couverture de code est un indicateur de test logiciel qui mesure le pourcentage de code source exécuté par vos tests automatisés. Elle a un impact direct sur la qualité du logiciel et la confiance dans le déploiement.

- Pour mesurer la couverture de code, il faut commencer par choisir les bons indicateurs (couverture par ligne, par branche, par condition et par chemin) et utiliser des outils tels que Qodana, JaCoCo, Istanbul/NYC, Coverage.py ou Jest pour générer des rapports de couverture dans votre pipeline d’intégration continue (CI).

- Viser une couverture de code de 80 % est généralement considéré comme un bon objectif pour la logique métier critique, mais atteindre une couverture de code de 100 % est souvent irréalisable et coûteux. Une couverture élevée ne garantit jamais un logiciel exempt de bogues.

- Pour améliorer la couverture de code, utilisez les rapports de couverture afin d’identifier les parties du code non testées, de hiérarchiser les modules à risque et d’intégrer des vérifications de couverture dans votre workflow CI/CD.

- Pour mieux comprendre comment la couverture s’intègre aux vérifications structurelles et stylistiques, consultez notre guide dédié à l’analyse statique du code.

Qu’est-ce que la couverture de code ?

La couverture de code mesure le pourcentage de code exécuté lors des tests. Si votre base de code comporte 1 000 lignes de code exécutables et que votre suite de tests en exécute 900, vous obtenez une couverture de 90 %. Elle est généralement exprimée en pourcentage et sert de métrique d’exécution — ce qui signifie qu’elle suit ce qui s’exécute réellement, et non ce qui pourrait poser problème sur la seule base de la structure.

Cela la distingue de l’analyse statique du code, qui inspecte le code source sans exécution pour signaler la complexité, les problèmes de style ou les indices de vulnérabilité. Les deux sont complémentaires : l’analyse statique vous indique où des problèmes pourraient se cacher, et la couverture de code vous indique si vos tests atteignent réellement ces zones.

Il convient de clarifier la différence entre la couverture de code et ce que l’on appelle parfois la couverture de test :

- La couverture de code se concentre sur la quantité de code source exécutée lors de l’exécution d’une suite de tests : lignes, branches, conditions.

- La couverture de test est plus large. Elle cherche à savoir si les exigences métier et les comportements des utilisateurs ont été validés, même si toutes les lignes pertinentes ont été exécutées.

Par exemple, une suite de tests peut exécuter 95 % des lignes d’un module de paiement, ce qui donne une couverture de ligne élevée. Mais si aucun test ne vérifie qu’un paiement échoue correctement en cas de solde négatif, les mesures de couverture de test pour ce comportement sont incomplètes.

La couverture de code identifie le code non testé, ce qui permet aux développeurs d’améliorer leurs efforts de test, en particulier dans les parties critiques telles que l’authentification, les couches d’accès aux données et la gestion des erreurs. Mesurer la couverture de code aide à découvrir des chemins non testés et des cas limites qui pourraient masquer des régressions ou des problèmes de sécurité.

Voici un exemple rapide en JavaScript :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
function foo(a, b) {

let c = 42

if (a > 0 && b > 0)

c = c + a * b

return c

}


Si votre seul test appelle foo(1, 1), toutes les lignes s'exécutent, mais la branche « else » n'est jamais testée. La couverture de ligne semble complète ; la couverture de branche révèle cette lacune.

Indicateurs et critères de couverture du code de base

Les critères de couverture sont des règles formelles permettant de déterminer le degré d’exhaustivité de l’exécution de votre code lors des tests. Plutôt que de chercher à atteindre tous les indicateurs simultanément, les équipes obtiennent de meilleurs résultats en sélectionnant un petit ensemble d’indicateurs de couverture principaux et en concentrant leurs efforts sur ceux-ci. Voici les types de couverture courants que vous rencontrerez.

Nom : 1.jpg
Affichages : 538
Taille : 113,4 Ko

La couverture de ligne et la couverture d’instruction sont souvent présentées sous la forme d’un pourcentage unique par la plupart des outils, ce qui en fait les indicateurs de référence les plus simples. Cependant, une couverture de ligne élevée ne signifie pas nécessairement que les autres indicateurs affichent des scores élevés. Par exemple, si nous avions 5 fonctions, dont 4 comportent 1 ligne et la dernière 100 lignes dans son corps, et que les tests ne couvraient que cette dernière, la couverture du code serait de près de 100 %, mais la couverture des fonctions ne serait que de 20 %.

La couverture des conditions va plus loin. Pour une expression composée telle que if (a && b || c), la couverture des conditions exige que chaque sous-expression booléenne (a, b, c) soit évaluée à la fois comme vraie et comme fausse dans l’ensemble de vos cas de test. Cela peut révéler des tests manquants que la couverture des branches seule pourrait masquer.

La couverture complète des chemins est pratiquement impossible pour les applications non triviales en raison de l’explosion combinatoire : les boucles et les branches imbriquées multiplient les chemins de code de manière exponentielle. Elle ne reste utile que pour des algorithmes particulièrement critiques.

Dans les domaines où la sécurité est critique, des critères plus avancés tels que la couverture conditionnelle/décisionnelle modifiée (MC/DC) sont obligatoires. La norme DO-178C, par exemple, exige la couverture conditionnelle/décisionnelle modifiée (MC/DC) pour les logiciels avioniques de niveau A, démontrant ainsi que chaque condition influence indépendamment le résultat de chaque décision.

Comment mesurer la couverture de code dans la pratique

Voici comment mesurer la couverture de code en quatre étapes :

1. Instrumentez votre code – Instrumentez votre code en introduisant des hooks qui permettent aux outils de couverture d’observer l’exécution. Cela peut se faire par instrumentation du code source, du bytecode ou en temps d’exécution.

2. Exécutez vos tests automatisés – tests unitaires, tests d’intégration ou tests de couverture de bout en bout.

3. Collectez les données de couverture – enregistrez les lignes, les branchements et les conditions qui ont été exécutés.

4. Générez des rapports de couverture – tableaux de bord HTML, résumés en terminal ou formats lisibles par machine (Cobertura XML, LCOV).

Exécution de la couverture en pratique

Qodana prend en charge les rapports de couverture générés par toute une gamme d’outils courants, notamment :

- JaCoCo (Java/Kotlin)
- Jest et Istanbul/nyc (JavaScript/TypeScript)
- pytest-cov (Python)
- Coverlet (.NET)
- PHPUnit (PHP)
- go test (Go)

Consultez la documentation de Qodana pour obtenir des instructions de configuration spécifiques à chaque langage.

Métriques de couverture

La couverture est généralement exprimée en pourcentage des éléments de code exécutés lors des tests :

- Couverture en lignes = nombre de lignes exécutables exécutées ÷ nombre total de lignes exécutables.
- Couverture des branches = nombre de branches exécutées ÷ nombre total de branches.

Différentes métriques offrent différents niveaux de confiance. La couverture de ligne indique quel code a été exécuté, tandis que la couverture de branche révèle si chaque chemin de décision a été testé.

La mesure de la couverture de code implique l’utilisation d’outils qui analysent les parties exécutées du code source, puis affichent ces résultats là où les développeurs peuvent en tirer parti : dans les commentaires des pull requests, les plugins d’EDI ou les tableaux de bord d’intégration continue (CI). Les calculs exacts de la couverture peuvent varier légèrement d’un outil à l’autre et d’un langage à l’autre, mais la couverture de ligne et la couverture de branche sont les métriques les plus couramment utilisées.

Nom : 2.jpg
Affichages : 506
Taille : 51,1 Ko

Comprendre les pourcentages de couverture et ce qu’est une « bonne » couverture de code

Les chiffres de couverture présentés en tête d’affiche peuvent être trompeurs s’ils sont considérés isolément. Un projet présentant une couverture de ligne de 85 % peut tout de même n’avoir qu’une couverture de branche de 55 %, laissant ainsi une logique complexe insuffisamment testée. Les métriques de couverture fournissent des informations sur l’exécution des tests plutôt que sur leur qualité. Un test qui exécute chaque ligne mais ne vérifie rien donne un faux sentiment de sécurité.

Alors, qu’est-ce qui constitue une bonne couverture ? Voici quelques recommandations pratiques :

- Google considère qu’une couverture de code de 60 % est acceptable et de 90 % exemplaire pour l’ensemble de ses projets.
- Le consensus parmi les développeurs suggère de viser une couverture de 70 % à 80 % afin de trouver un équilibre entre qualité et évitement de la suringénierie.
- Une étude a révélé une couverture de code moyenne de 74 à 76 % sur 47 projets, ce qui suggère que la plupart des équipes se situent dans une fourchette similaire.
- UJET a maintenu une exigence de couverture de code de 85 % en utilisant un outil permettant d’assurer la visibilité et le suivi des tendances.

Pour beaucoup, viser une couverture de 80 % constitue une norme saine du secteur pour la logique métier critique. Cependant, une couverture de code de 100 % ne garantit pas un code exempt de bogues : cela signifie simplement que chaque ligne a été testée, et non que chaque comportement a été validé.

Définissez des seuils en fonction du niveau de risque :

- Modules de transactions financières, flux d’authentification → 85 à 90 %
- Logique métier générale → 70 à 80 %
- Code généré ou standard → à exclure totalement des seuils

Considérez la couverture comme un indicateur de tendance dans le temps (d’une semaine à l’autre, d’un sprint à l’autre) plutôt que comme un objectif ponctuel. Une couverture élevée met en évidence les risques liés au code hérité ou non testé lorsque les chiffres commencent à baisser. Les tableaux de bord qui visualisent cette tendance aident les équipes à repérer les régressions avant qu’elles ne s’aggravent.

Comment améliorer la couverture de code sans sacrifier la qualité

Pour améliorer la couverture de code de manière significative, considérez-la comme un guide pratique et non comme un objectif abstrait. Voici une approche étape par étape qui place la qualité logicielle au premier plan.

1. Commencez par vos rapports de couverture. Utilisez-les pour identifier les sections de code non testées, en vous concentrant sur les zones à haut risque et à faible couverture de code, telles que les services métier clés, le traitement des paiements et les couches d’accès aux données. N’essayez pas d’augmenter uniformément le pourcentage global de couverture.

2. Écrivez d’abord des tests unitaires ciblés. Les tests unitaires permettent d’augmenter rapidement la couverture de code, car ils ciblent des fonctions isolées et pures, ainsi que de petits composants. Utilisez des frameworks tels que JUnit 5, pytest ou Jest pour écrire des tests supplémentaires autour des fonctions ayant le plus grand impact métier.

3. Ciblez les branches et les conditions non couvertes. La couverture par ligne reste la méthode la plus courante pour mesurer la part du code exercée par les tests automatisés. Cependant, vous pouvez aller au-delà. Rédigez des cas de test qui explorent les chemins d’erreur, la logique de réessai, la gestion des délais d’expiration et les cas limites dans une logique complexe. Cela augmentera la couverture du code au niveau des branches et des conditions, là où les bogues se cachent le plus souvent.

4. Refactorisez le code trop complexe. Les fonctions présentant une complexité cyclomatique très élevée sont difficiles à tester et à couvrir. Les diviser en unités plus petites et testables améliore à la fois les chiffres de couverture et les résultats de l’analyse statique.

5. Gérez le code difficile à tester. Pour les intégrations tierces, les modules hérités ou le code impliquant de nombreuses opérations d’E/S, utilisez l’injection de dépendances, la simulation (mocking), les doubles de test et les tests de contrat. Ces stratégies permettent d’écrire des tests sans avoir besoin d’environnements externes complets.

6. Intégrez des contrôles de couverture dans la CI. Intégrez des outils de couverture de code dans votre pipeline de CI et fixez-vous un objectif de 80 %, puis suivez vos progrès. Imposez la règle « aucune régression significative de la couverture par pull request » à l’aide de contrôles d’état de couverture sur GitHub, GitLab ou Azure DevOps.

7. Fixez des objectifs de couverture réalistes en fonction de la criticité du projet. Tous les fichiers ne méritent pas le même objectif. Définissez des objectifs de couverture par module plutôt que de manière globale.

Évitez d’écrire des tests superficiels dans le seul but d’augmenter le pourcentage de couverture. Les tests utiles doivent vérifier des comportements significatifs, des cas limites et des conditions d’erreur – et non pas simplement exécuter des lignes de code.
La couverture de code améliore la fiabilité du code en vérifiant les chemins critiques et la logique, mais uniquement lorsque les tests eux-mêmes sont pertinents. La couverture de code renforce l’assurance qualité en mesurant l’exhaustivité des tests, et non en gonflant les chiffres.

Intégration de la couverture de code aux workflows d’analyse statique et de CI/CD

La combinaison d’outils de couverture avec des plateformes d’analyse statique de code vous offre une vision plus complète de la santé du code : des métriques d’exécution en temps réel ainsi que des vérifications structurelles et stylistiques sur plusieurs langages de programmation.

Présentation du rapport

Une fois le projet préparé et l'analyse de couverture de code exécutée, vous pouvez consulter les rapports de couverture de code dans Qodana Cloud ou via votre EDI.

Qodana Cloud

Les statistiques de couverture de code s'affichent dans le coin supérieur droit de l'interface utilisateur des rapports Qodana. Elles indiquent également la liste des inspections utilisées par la fonctionnalité.

Nom : 3.jpg
Affichages : 525
Taille : 62,8 Ko

EDI

Vous pouvez consulter les rapports de couverture de code à l'aide des IDE IntelliJ IDEA, WebStorm, PhpStorm, PyCharm et GoLand. Cette fonctionnalité est disponible pour les rapports récupérés depuis Qodana Cloud après mise en relation, ou pour les rapports provenant du stockage local.

Actuellement, la vue d'ensemble de la couverture de code n'est pas disponible pour les rapports au format XML générés par les rapports de couverture .NET.
Ouvrir des rapports depuis Qodana Cloud

1. Dans votre EDI, accédez à Outils | Qodana | Se connecter à Qodana

Nom : 4.jpg
Affichages : 512
Taille : 38,2 Ko

2. Dans la boîte de dialogue « Paramètres », cliquez sur « Se connecter ».

Nom : 5.jpg
Affichages : 507
Taille : 44,2 Ko

Vous serez alors redirigé vers la page d'authentification.

3. Dans la boîte de dialogue Paramètres, recherchez le projet auquel vous souhaitez vous connecter.

Nom : 6.jpg
Affichages : 509
Taille : 27,0 Ko

Afficher les rapports de couverture dans l'EDI

Vous pouvez consulter les rapports de couverture de code en local à l'aide des EDI JetBrains.

Dans votre EDI, accédez à Exécuter | Afficher les données de couverture et ouvrez le fichier contenant un rapport de couverture de code.

Nom : 7.jpg
Affichages : 509
Taille : 54,4 Ko

Dans la fenêtre d'outils Couverture, vous pouvez consulter le rapport de couverture des tests. Ce rapport indique le pourcentage du code qui a été exécuté ou couvert par les tests.

Nom : 8.jpg
Affichages : 511
Taille : 32,0 Ko

Présentation du rapport

L’EDI met en évidence la couverture de test du code à l’aide d’un marquage couleur. Par défaut, la couleur verte indique qu’une ligne donnée a été couverte, tandis que la couleur rouge signale une ligne de code non couverte.

Si les résultats de couverture de code vous semblent incomplets, vous devrez probablement reconfigurer votre outil de couverture de code et générer un nouveau rapport de couverture de code.
Nom : 9.jpg
Affichages : 505
Taille : 33,8 Ko

Le rapport indique la couverture des lignes qui implémentent la logique d’une méthode, d’une fonction ou d’une classe, mais pas celle de la déclaration de la fonction, de la méthode ou de la classe. L’image ci-dessous montre que la couverture de code ne s’applique pas à la ligne 7, tandis que la ligne 8 n’est pas couverte.

Nom : 10.jpg
Affichages : 504
Taille : 14,6 Ko

Avec Qodana, vous pouvez consulter la couverture de code dans votre tableau de bord Insights.

Nom : 11.jpg
Affichages : 535
Taille : 54,5 Ko

Pièges courants et idées reçues concernant une couverture de code élevée

Une couverture de code élevée peut donner un faux sentiment de sécurité. Prenons l’exemple d’une suite de tests présentant une couverture de code de 100 % au niveau des lignes : si les assertions sont faibles ou font totalement défaut, des bogues graves peuvent passer inaperçus. L’exécution seule ne constitue pas une validation.

Pièges à éviter :

- Ignorer complètement les autres types de couverture. Qodana prend en charge à la fois la couverture globale des lignes et la couverture des nouvelles lignes, ce qui permet aux équipes de s’assurer que le code nouvellement ajouté ou modifié est correctement testé, tout en améliorant progressivement la couverture du reste de la base de code. Cependant, nous vous encourageons à explorer d’autres types de couverture au fil du temps, tels que la couverture des branches.

- Utiliser la couverture comme indicateur de performance. Lorsqu’un pourcentage de couverture global unique devient un indicateur clé de performance (KPI) de l’équipe, cela incite à maintenir des tests superficiels — juste assez pour atteindre le chiffre visé. Cela peut ralentir le processus de développement sans apporter de bénéfice significatif.

- Imposer la couverture à du code non testable. Le code généré, les getters/setters triviaux et le code de liaison des frameworks ne nécessitent légitimement pas de tests. Tenter d’imposer une couverture dans ces cas-là représente un gaspillage d’efforts. Excluez-les des seuils.

- Oublier ce que la couverture ne mesure pas. Les outils de couverture n’évaluent pas si toutes les exigences métier, les parcours utilisateurs ou les aspects non fonctionnels (performances, sécurité, ergonomie) sont correctement testés. Ils indiquent uniquement quel code a été exécuté.

Microsoft Research a examiné plus de 100 grands projets Java open source et a constaté une corrélation négligeable entre une couverture élevée et un nombre réduit de défauts post-lancement au niveau des fichiers. Cela confirme que la couverture est nécessaire mais non suffisante : il faut la mettre en balance avec les tendances en matière de défauts, les analyses rétrospectives des incidents, les avertissements d’analyse statique et la surveillance en production.

Essayez Qodana gratuitement

FAQ

Une couverture de code à 100 % est-elle parfois requise dans des projets concrets ?

Oui, dans les domaines critiques pour la sécurité. Les logiciels aérospatiaux soumis à la norme DO-178C et les systèmes automobiles soumis à la norme ISO 26262 peuvent exiger une couverture proche de 100 % au niveau des instructions, des branchements et des conditions de gestion (MC/DC), en fonction d’un ou plusieurs critères liés aux niveaux d’intégrité de sécurité. Pour la plupart des applications web et mobiles commerciales, une couverture de code de 80 % est généralement considérée comme un bon objectif pour les modules centraux, les gains devenant décroissants au-delà de ce seuil. La qualité des tests et une approche axée sur les risques priment sur la recherche d’une couverture à 100 % sur l’ensemble de la base de code.

À quelle fréquence dois-je effectuer une analyse de couverture dans mon projet ?

Effectuez une analyse de couverture sur chaque pull request dans les dépôts actifs afin que les régressions soient détectées immédiatement. Pour les grands projets logiciels dont l’intégration est plus lente et qui disposent déjà de tests de bout en bout, programmez une tâche de couverture complète chaque nuit ou chaque semaine. Utilisez les données de tendance pour orienter les investissements en refactorisation et déterminer où des tests supplémentaires sont les plus nécessaires.

Quelle métrique de couverture dois-je privilégier en premier : la couverture de ligne, la couverture de branche ou autre chose ?

Commencez par la couverture de ligne, qui constitue une base de référence simple et facile à communiquer aux parties prenantes. Une fois que votre équipe est à l’aise avec cette approche, introduisez la couverture de branche comme métrique principale pour la logique métier non triviale. La couverture de condition et la couverture de chemin sont particulièrement utiles dans les vérifications d’autorisation de code très complexes et à haut risque, les moteurs de tarification ou tout programme comportant des structures de contrôle profondément imbriquées ; elles peuvent être adoptées de manière sélective plutôt qu’à l’échelle du projet.

En quoi l’analyse statique du code et la couverture de code se complètent-elles ?

L’analyse statique signale les problèmes potentiels sans exécuter le code, notamment le code mort, les déréférencements de valeurs nulles et les indices de failles de sécurité. La couverture de code montre quelles parties du code source sont réellement exécutées par les tests. Ensemble, elles créent une boucle de rétroaction : l’analyse statique identifie les zones complexes ou à risque, les rapports de couverture révèlent si elles sont suffisamment couvertes, et les développeurs hiérarchisent en conséquence la création de nouveaux tests ou les refactorisations.

Puis-je utiliser la couverture de code pour des tests manuels ou uniquement pour des tests automatisés ?

Les outils de couverture fonctionnent par défaut avec les tests automatisés, mais ils peuvent également collecter des données lors de l’exécution de tests exploratoires manuels sur une application instrumentée. Cela s’avère utile pendant les phases de consolidation préalables à la mise en production pour confirmer quelles fonctionnalités ont été exécutées. Les scénarios manuels les plus pertinents peuvent ensuite être convertis en tests automatisés afin de préserver cette couverture au fil du temps dans l’ensemble de vos projets logiciels.

Remarque : bien que les exemples présentés dans cet article utilisent des outils de couverture spécifiques, Qodana n’est lié à aucune solution particulière. Tout outil produisant un format de rapport de couverture pris en charge peut être utilisé.

Essayez Qodana gratuitement