Qu'est-ce qu'un% de couverture de code raisonnable pour les tests unitaires (et pourquoi)? [fermé]

605

Si vous deviez imposer un pourcentage minimum de couverture de code pour les tests unitaires, peut-être même comme exigence pour vous engager dans un référentiel, quel serait-il?

Veuillez expliquer comment vous êtes arrivé à votre réponse (puisque si tout ce que vous avez fait était de choisir un numéro, alors j'aurais pu le faire tout seul;)

santé mentale
la source
De nos jours, de nombreux IDE sont fournis avec une mise en évidence de la couverture, assurez-vous de couvrir les parties les plus importantes du code au moins de penser à atteindre un pourcentage donné.
Tous les
4
Le symbole% est une odeur de code pour les mesures (également% est une odeur de conneries en général)
Hernán Eche
Les tests unitaires par définition peuvent être des méthodes individuelles, des classes entières ou des modules entiers. Même si vous testez toutes les méthodes, il se peut que vous ne testiez pas tous les chemins ou toutes les combinaisons qu'un utilisateur atteindra. La situation devient plus complexe avec le relevé, la couverture des succursales et les MCDC.
Ska
Pourquoi cette question n'est-elle pas supprimée ou correctement modifiée? Cela a suscité tellement d'intérêt, mais c'est totalement trompeur.
Ska

Réponses:

1391

Cette prose d'Alberto Savoia répond précisément à cette question (d'une manière bien amusante à cela!):

http://www.artima.com/forums/flat.jsp?forum=106&thread=204677

Testivus sur la couverture des tests

Tôt un matin, un programmeur a demandé au grand maître:

«Je suis prêt à écrire des tests unitaires. Quelle couverture de code dois-je viser? "

Le grand maître a répondu:

"Ne vous inquiétez pas de la couverture, écrivez simplement de bons tests."

Le programmeur sourit, s'inclina et partit.

...

Plus tard dans la journée, un deuxième programmeur a posé la même question.

Le grand maître montra du doigt une marmite d'eau bouillante et dit:

"Combien de grains de riz dois-je mettre dans ce pot?"

Le programmeur, l'air perplexe, a répondu:

«Comment puis-je vous le dire? Cela dépend du nombre de personnes que vous devez nourrir, de leur faim, de la nourriture que vous servez, de la quantité de riz disponible, etc. »

"Exactement", a déclaré le grand maître.

Le deuxième programmeur sourit, s'inclina et partit.

...

Vers la fin de la journée, un troisième programmeur est venu et a posé la même question sur la couverture du code.

"Quatre-vingt pour cent et pas moins!" Répondit le maître d'une voix sévère, tapant du poing sur la table.

Le troisième programmeur sourit, s'inclina et partit.

...

Après cette dernière réponse, un jeune apprenti s'approcha du grand maître:

«Grand maître, aujourd'hui, je vous ai entendu répondre à la même question sur la couverture du code avec trois réponses différentes. Pourquoi?"

Le grand maître se leva de sa chaise:

"Venez prendre du thé frais avec moi et parlons-en."

Après avoir rempli leurs tasses de thé vert chaud fumant, le grand maître a commencé à répondre:

«Le premier programmeur est nouveau et ne fait que commencer les tests. En ce moment, il a beaucoup de code et aucun test. Il a un long chemin à parcourir; se concentrer sur la couverture du code en ce moment serait déprimant et tout à fait inutile. Il vaut mieux s'habituer à écrire et à exécuter des tests. Il peut s'inquiéter de la couverture plus tard. »

«Le second programmeur, quant à lui, possède une grande expérience en programmation et en test. Quand je lui ai répondu en lui demandant combien de grains de riz je devrais mettre dans un pot, je l'ai aidée à réaliser que la quantité de tests nécessaires dépend d'un certain nombre de facteurs, et elle connaît ces facteurs mieux que moi - c'est son code après tout . Il n'y a pas de réponse simple et simple, et elle est assez intelligente pour gérer la vérité et travailler avec cela. »

"Je vois", a déclaré le jeune apprenti, "mais s'il n'y a pas de réponse simple, alors pourquoi avez-vous répondu au troisième programmeur" Quatre-vingt pour cent et pas moins "?"

Le grand maître rit si fort et si fort que son ventre, preuve qu'il buvait plus que du thé vert, se balança de haut en bas.

"Le troisième programmeur ne veut que des réponses simples - même quand il n'y a pas de réponses simples ... et ne les suit pas de toute façon."

Le jeune apprenti et le grand maître grisonnant finirent de boire leur thé dans un silence contemplatif.

Jon Limjap
la source
62
Cela ressemble à un argument contre le concept général de couverture de code, en tant que métrique pour évaluer l'utilité des tests unitaires. Je suis sûr que tout le monde convient que ce n'est pas une métrique parfaite, mais l'expérience personnelle devrait, espérons-le, montrer une certaine corrélation entre le CC% et l'efficacité des tests unitaires ...
sanity
16
santé mentale - votre déclaration est reflétée précisément par la réponse du "deuxième développeur". L'expérience personnelle doit la dicter.
Jon Limjap
167
Réponse parfaite. Les métriques ne font pas un bon code. Vous pouvez écrire du code merdique avec une couverture à 100% et cela ne fait pas fonctionner le code correctement. +1 de moi, dommage que je ne puisse plus me lever :)
Rob Cooper
15
4 ans plus tard, et toujours utile. Je viens de tirer ceci sur deux de mes collègues ce matin.
SickHippie
9
Pour moi, cette anecdote représente une vision idéaliste. Dans le monde réel des équipes de projet avec des priorités concurrentes, la couverture du code passe à 0%. Nous avons besoin d'un nombre requis afin de construire l'habitude des tests unitaires au sein de l'équipe. Je suis venu à cette question à la recherche de conseils sur la détermination de ce nombre pour un domaine que je ne connais pas très bien, et ce n'est vraiment pas du tout utile. Je suis heureux que les gens dans d'autres scénarios le trouvent utile.
samspot
86

La couverture du code est une mesure trompeuse si une couverture à 100% est votre objectif (au lieu de tester à 100% toutes les fonctionnalités).

  • Vous pourriez obtenir un 100% en frappant toutes les lignes une fois. Cependant, vous pourriez toujours manquer de tester une séquence particulière (chemin logique) dans laquelle ces lignes sont frappées.
  • Vous n'avez pas pu obtenir un 100% mais vous avez quand même testé tous vos chemins de code utilisés à 80% / freq. Avoir des tests qui testent chaque `` lancer ExceptionTypeX '' ou un garde de programmation défensive similaire que vous avez installé est un `` bien d'avoir '' pas un `` must have ''

Faites donc confiance à vous ou à vos développeurs pour être minutieux et parcourir tous les chemins à travers leur code. Soyez pragmatique et ne poursuivez pas la couverture magique à 100%. Si vous TDD votre code, vous devriez obtenir une couverture de 90% + en bonus. Utilisez la couverture de code pour mettre en évidence des morceaux de code que vous avez manqués (cela ne devrait pas se produire si vous TDD .. car vous n'écrivez du code que pour réussir un test. Aucun code ne peut exister sans son test partenaire.)

Gishu
la source
4
- Exceptions - si vous ne testez pas votre gestion des exceptions, comment savez-vous que votre code ne saute pas quand cela se produit? - Setters / Getters - context contextuel je suppose, mais vos tests devraient sûrement les exécuter dans le cadre de la suite de tests, et s'ils ne sont pas réellement utilisés?
tddmonkey
1
Les exceptions devraient être exceptionnelles - pas censées se produire. S'ils le font, vous enregistrez le point d'échec et la caution. Vous ne pouvez pas tester toutes les exceptions qui pourraient se produire. Si l'application est censée gérer un chemin / événement non satisfaisant, vous devriez le tester. Des accessoires peuvent être ajoutés pour les futurs clients .. dépend
Gishu
5
Je ne sais pas ce que vous entendez par votre deuxième point "mais j'ai quand même testé tous vos chemins de code". Si vous entendez en fait une couverture complète, alors non, vous ne pouvez pas avoir une couverture complète sans couverture 100% ligne / succursale / décision. En fait, la couverture de chemin complet est généralement impossible à obtenir dans un programme non trivial en raison de la nature combinatoire des branches lors de la génération de chemins. en.wikipedia.org/wiki/Code_coverage#Other_coverage_criteria
Zach Burlingame
3
Vous ne testez pas toutes les exceptions possibles; bien sûr, vous ne pouvez pas faire ça. Vous DEVRIEZ viser à tester chaque bloc de code qui gère les exceptions. Par exemple, si vous avez besoin que lorsque le bloc X lève une exception, l'exception est enregistrée dans la base de données, la bande verte en bas de l'écran devient rouge et un e-mail est envoyé au Pape; c'est ce que vous devez tester. Mais vous n'avez pas à tester toutes les exceptions possibles qui pourraient déclencher ces événements.
Dawood ibn Kareem
2
+1 pour "Utiliser la couverture de code pour mettre en évidence des morceaux de code que vous avez manqués". C'est essentiellement pour cela que cette métrique est bonne.
beluchin
61

La couverture du code est excellente, mais la couverture des fonctionnalités est encore meilleure. Je ne crois pas à couvrir chaque ligne que j'écris. Mais je crois en écrivant une couverture de test à 100% de toutes les fonctionnalités que je veux fournir (même pour les fonctionnalités extra cool que je suis venu avec moi-même et qui n'ont pas été discutées lors des réunions).

Je ne me soucie pas d'avoir du code qui n'est pas couvert par les tests, mais je me soucierais de refactoriser mon code et de finir par avoir un comportement différent. Par conséquent, une couverture de fonctionnalité à 100% est ma seule cible.

tofi9
la source
4
Ceci est une réponse fantastique. Un code qui répond à ses exigences est un objectif beaucoup plus intéressant que le code qui répond à une mesure de couverture LoC arbitraire.
Dawood ibn Kareem
46
Si vous pouvez fournir toutes les fonctionnalités sans toucher à toutes les lignes de code, que font alors ces lignes de code supplémentaires?
Jens Timmerman
4
@JensTimmerman vous avez théoriquement raison. Cependant, une couverture de code à 100% est trop coûteuse dans le temps, et forcer mon équipe à le faire non seulement les démotive, mais fait également fonctionner mon projet dans les délais. J'aime être quelque part au milieu, et tester la fonctionnalité (appelez-le: test d'intégration) est ce avec quoi je me sens à l'aise. Quel code je ne teste pas? Gestion des exceptions techniques, (plage / paramètre) vérifications qui pourraient être nécessaires. En bref, toute la plomberie technique que j'ai appris à appliquer à partir de sa propre expérience ou des meilleures pratiques que j'ai lues.
tofi9
2
J'ai fait un pas de plus en faisant une liste de situations courantes qui devraient être incluses ou exclues des tests. De cette façon, nous n'atteignions jamais un pourcentage, mais plutôt une couverture fonctionnelle de toutes les parties de la base de code fonctionnelle.
Skeeterdrums
58

La réponse acceptée fait un bon point - il n'y a pas un seul chiffre qui va avoir du sens comme standard pour chaque projet. Il y a des projets qui n'ont tout simplement pas besoin d'une telle norme. À mon avis, la réponse acceptée ne suffit pas à décrire comment on pourrait prendre cette décision pour un projet donné.

Je vais tenter de le faire. Je ne suis pas un expert en ingénierie de test et serais heureux de voir une réponse plus éclairée.

Quand définir les exigences de couverture du code

Premièrement, pourquoi voudriez-vous imposer une telle norme en premier lieu? En général, lorsque vous souhaitez introduire une confiance empirique dans votre processus. Qu'est-ce que j'entends par «confiance empirique»? Eh bien, le vrai objectif correct . Pour la plupart des logiciels, nous ne pouvons pas le savoir sur toutes les entrées, nous nous contentons donc de dire que le code est bien testé . C'est plus connu, mais c'est toujours une norme subjective: il sera toujours possible de débattre si vous l'avez ou non respecté. Ces débats sont utiles et devraient avoir lieu, mais ils révèlent également des incertitudes.

La couverture du code est une mesure objective: une fois que vous voyez votre rapport de couverture, il n'y a aucune ambiguïté quant à savoir si les normes ont été respectées sont utiles. Prouve-t-elle l'exactitude? Pas du tout, mais cela a une relation claire avec la qualité du test du code, ce qui est à notre tour notre meilleure façon d'augmenter la confiance dans son exactitude. La couverture du code est une approximation mesurable des qualités incommensurables dont nous nous soucions.

Quelques cas spécifiques où avoir une norme empirique pourrait ajouter de la valeur:

  • Pour satisfaire les parties prenantes. Pour de nombreux projets, divers acteurs intéressés par la qualité du logiciel peuvent ne pas être impliqués dans le développement quotidien du logiciel (gestionnaires, responsables techniques, etc.) en disant "nous allons écrire tous les tests dont nous avons vraiment besoin "n'est pas convaincant: ils doivent soit faire entièrement confiance, soit vérifier avec une étroite surveillance continue (en supposant qu'ils ont même la compréhension technique pour le faire.) Fournir des normes mesurables et expliquer comment ils se rapprochent raisonnablement des objectifs réels est mieux.
  • Pour normaliser le comportement de l'équipe. Parties prenantes mises à part, si vous travaillez dans une équipe où plusieurs personnes écrivent du code et des tests, il y a place à l'ambiguïté pour ce qui est qualifié de "bien testé". Tous vos collègues ont-ils la même idée du niveau de test suffisant? Probablement pas. Comment conciliez-vous cela? Trouvez une métrique sur laquelle vous pouvez tous vous mettre d'accord et l'accepter comme une approximation raisonnable. Ceci est particulièrement (mais pas exclusivement) utile dans les grandes équipes, où les prospects peuvent ne pas avoir de supervision directe sur les développeurs juniors, par exemple. Les réseaux de confiance sont également importants, mais sans mesures objectives, le comportement du groupe peut facilement devenir incohérent, même si tout le monde agit de bonne foi.
  • Pour rester honnête. Même si vous êtes le seul développeur et la seule partie prenante de votre projet, vous pourriez avoir certaines qualités en tête pour le logiciel. Au lieu de faire des évaluations subjectives continues sur le niveau de test du logiciel (ce qui prend du travail), vous pouvez utiliser la couverture du code comme une approximation raisonnable et laisser les machines la mesurer pour vous.

Quelles mesures utiliser

La couverture du code n'est pas une métrique unique; il existe plusieurs façons différentes de mesurer la couverture. Lequel vous pouvez définir une norme dépend de ce que vous utilisez pour satisfaire.

J'utiliserai deux mesures courantes comme exemples de cas où vous pourriez les utiliser pour définir des normes:

  • Couverture des relevés : quel pourcentage des relevés ont été exécutés lors des tests? Utile pour avoir une idée de la couverture physique de votre code: Quelle partie du code que j'ai écrit ai-je réellement testée?
    • Ce type de couverture prend en charge un argument de correction plus faible, mais est également plus facile à réaliser. Si vous utilisez simplement la couverture de code pour vous assurer que les choses sont testées (et non comme un indicateur de la qualité du test au-delà de cela), la couverture des instructions est probablement suffisante.
  • Couverture des succursales : Lorsqu'il y a une logique de branchement (par exemple un if), les deux branches ont-elles été évaluées? Cela donne une meilleure idée de la couverture logique de votre code: combien de chemins possibles mon code peut-il avoir testés?
    • Ce type de couverture est un bien meilleur indicateur qu'un programme a été testé sur un ensemble complet d'intrants. Si vous utilisez la couverture de code comme meilleure approximation empirique pour la confiance dans l'exactitude, vous devez définir des normes basées sur la couverture de branche ou similaire.

Il existe de nombreuses autres mesures (la couverture de ligne est similaire à la couverture de relevé, mais donne des résultats numériques différents pour les relevés multilignes, par exemple; la couverture conditionnelle et la couverture de chemin sont similaires à la couverture de branche, mais reflètent une vue plus détaillée des permutations possibles de exécution de programme que vous pourriez rencontrer.)

Quel pourcentage exiger

Enfin, revenons à la question d'origine: si vous définissez des normes de couverture de code, quel devrait être ce nombre?

J'espère qu'il est clair à ce stade que nous parlons d'une approximation pour commencer, donc tout chiffre que nous choisirons sera intrinsèquement approximatif.

Quelques chiffres que l'on pourrait choisir:

  • 100% . Vous pouvez choisir ceci parce que vous voulez être sûr que tout est testé. Cela ne vous donne aucun aperçu de la qualité du test, mais vous indique qu'un test d'une certaine qualité a touché chaque déclaration (ou succursale, etc.) Encore une fois, cela revient à un degré de confiance: si votre couverture est inférieure à 100% , vous savez qu'un sous-ensemble de votre code n'est pas testé.
    • Certains pourraient affirmer que c'est idiot, et vous ne devriez tester que les parties de votre code qui sont vraiment importantes. Je dirais que vous ne devez également conserver que les parties de votre code qui sont vraiment importantes. La couverture du code peut également être améliorée en supprimant le code non testé.
  • 99% (ou 95%, autres chiffres dans les années 90). Convient dans les cas où vous souhaitez transmettre un niveau de confiance similaire à 100%, mais laissez-vous une certaine marge pour ne pas vous soucier du coin occasionnellement difficile à tester de code.
  • 80% . J'ai vu ce numéro utilisé plusieurs fois, et je ne sais pas entièrement d'où il provient. Je pense que cela pourrait être un détournement étrange de la règle 80-20; généralement, l'intention ici est de montrer que la plupart de votre code est testé. (Oui, 51% serait également "la plupart", mais 80% reflète mieux ce que la plupart des gens entendent par la plupart.) Ceci est approprié pour les cas intermédiaires où "bien testé" n'est pas une priorité élevée (vous ne ' je ne veux pas gaspiller des efforts sur des tests de faible valeur), mais c'est une priorité suffisante pour que vous souhaitiez toujours avoir une norme en place.

Je n'ai pas vu de chiffres inférieurs à 80% dans la pratique, et j'ai du mal à imaginer un cas où l'on les fixerait. Le rôle de ces normes est d'accroître la confiance dans l'exactitude, et les chiffres inférieurs à 80% ne sont pas particulièrement inspirants. (Oui, c'est subjectif, mais encore une fois, l'idée est de faire le choix subjectif une fois lorsque vous définissez la norme, puis d'utiliser une mesure objective à l'avenir.)

Autres notes

Ce qui précède suppose que l'exactitude est le but. La couverture du code n'est qu'une information; il peut être pertinent pour d'autres objectifs. Par exemple, si vous êtes préoccupé par la maintenabilité, vous vous souciez probablement du couplage lâche, qui peut être démontré par la testabilité, qui à son tour peut être mesurée (dans certaines modes) par la couverture du code. Votre norme de couverture de code fournit donc une base empirique pour estimer également la qualité de la "maintenabilité".

killscreen
la source
Bonne réponse. Pouvez-vous m'aider à trouver une couverture fonctionnelle via des tests unitaires? Y a-t-il des outils qui peuvent m'aider à y parvenir?
curlyreggie
2
Très bonne réponse. C'est le seul qui se concentre sur les tests en tant que problème d'équipe dans un environnement industriel. Je ne passe pas tout en revue et mon équipe est très brillante, mais verte. J'ai fixé un plancher de pourcentage de 90% sur un nouveau projet comme test de santé mentale pour les développeurs juniors, pas parce que je pense que c'est "suffisant". "90%" et "positif, négatif et nul" sont des mantras faciles pour les jeunes développeurs brillants qui, je le sais, feront du bon travail, mais n'ont pas l'expérience pour aller de l'avant et écrire ce cas de test supplémentaire qui harcèle le au fond de votre esprit.
0x1mason
2
je pense que c'est la meilleure réponse disponible.
bugkiller
27

Ma couverture de code préférée est 100% avec un astérisque. L'astérisque vient parce que je préfère utiliser des outils qui me permettent de marquer certaines lignes comme des lignes qui "ne comptent pas". Si j'ai couvert 100% des lignes qui "comptent", j'ai terminé.

Le processus sous-jacent est:

  1. J'écris mes tests pour exercer toutes les fonctionnalités et les cas de bord auxquels je peux penser (en travaillant généralement à partir de la documentation).
  2. Je lance les outils de couverture de code
  3. J'examine toutes les lignes ou chemins non couverts et ceux que je considère comme non importants ou inaccessibles (en raison d'une programmation défensive) Je marque comme ne comptant pas
  4. J'écris de nouveaux tests pour couvrir les lignes manquantes et améliorer la documentation si ces cas marginaux ne sont pas mentionnés.

De cette façon, si moi et mes collaborateurs ajoutons du nouveau code ou modifions les tests à l'avenir, il y a une ligne claire pour nous dire si nous avons raté quelque chose d'important - la couverture est tombée en dessous de 100%. Cependant, il offre également la flexibilité nécessaire pour gérer différentes priorités de test.

Éponyme
la source
3
@ErikE Astérix est, bien sûr, un guerrier court mais intrépide de la Gaule qui crée des exceptions à l'occupation monotone romaine et donc le petit symbole typographique signalant les exceptions a été nommé d'après lui. (Plus sérieusement, merci, j'ai corrigé l'orthographe.)
Eponymous
3
Souhaitez-vous inclure les "outils qui vous permettent [de] marquer certaines lignes comme des lignes qui ne comptent pas"?
domdambrogia
2
@domdambrogia Comme exemple en PHP, si vous utilisez la bibliothèque de couverture de code de Bergmann, annotez une ligne avec // @codeCoverageIgnoreet elle sera exclue de la couverture.
évêque
19

Je voudrais avoir une autre anectode sur la couverture des tests que je voudrais partager.

Nous avons un énorme projet dans lequel, sur Twitter, j'ai remarqué qu'avec 700 tests unitaires, nous n'avons que 20% de couverture de code .

Scott Hanselman a répondu avec des paroles de sagesse :

Est-ce le BON 20%? Est-ce le 20% qui représente le code que vos utilisateurs ont le plus touché? Vous pouvez ajouter 50 tests supplémentaires et seulement 2%.

Encore une fois, cela revient à mon Testivus sur la réponse à la couverture de code . Combien de riz faut-il mettre dans le pot? Ça dépend.

Jon Limjap
la source
De toute évidence, il doit y avoir du bon sens là-dedans. Ce n'est pas très utile si les 50% du code que vous testez sont des commentaires.
sanity
2
C'est plus dans les lignes de ... votre couverture est-elle consacrée aux fonctionnalités de base de votre application, ou teste-t-elle inutilement des fonctionnalités triviales / sympathiques?
Jon Limjap
sonne comme un grand% de votre code est soit passe-partout, soit la gestion des exceptions, ou des trucs "mode de débogage" conditionnel
Erik Aronesty
8

Pour un système bien conçu, où les tests unitaires ont guidé le développement depuis le début, je dirais que 85% est un nombre assez faible. Les petites classes conçues pour être testables ne devraient pas être difficiles à couvrir mieux que cela.

Il est facile de rejeter cette question avec quelque chose comme:

  • Les lignes couvertes ne sont pas égales à la logique testée et il ne faut pas trop lire le pourcentage.

Certes, mais il y a quelques points importants à faire sur la couverture du code. D'après mon expérience, cette métrique est en fait très utile lorsqu'elle est utilisée correctement. Cela dit, je n'ai pas vu tous les systèmes et je suis sûr qu'il y en a des tonnes où il est difficile de voir une analyse de la couverture de code ajouter une valeur réelle. Le code peut sembler si différent et la portée du cadre de test disponible peut varier.

De plus, mon raisonnement concerne principalement des boucles de rétroaction de test assez courtes. Pour le produit que je développe, la boucle de rétroaction la plus courte est assez flexible, couvrant tout, des tests de classe à la signalisation inter-processus. Le test d'un sous-produit livrable prend généralement 5 minutes et pour une boucle de rétroaction aussi courte, il est en effet possible d'utiliser les résultats du test (et en particulier la mesure de couverture de code que nous examinons ici) pour rejeter ou accepter les validations dans le référentiel.

Lorsque vous utilisez la mesure de couverture de code, vous ne devez pas simplement avoir un pourcentage fixe (arbitraire) qui doit être respecté. À mon avis, cela ne vous donne pas les avantages réels de l'analyse de la couverture du code. Définissez plutôt les mesures suivantes:

  • Low Water Mark (LWM), le plus petit nombre de lignes découvertes jamais vu dans le système testé
  • High Water Mark (HWM), le pourcentage de couverture de code le plus élevé jamais vu pour le système testé

Un nouveau code ne peut être ajouté que si nous n'allons pas au-dessus du LWM et si nous n'allons pas au-dessous du HWM. En d'autres termes, la couverture du code ne doit pas diminuer et le nouveau code doit être couvert. Remarquez comment je dis devrait et ne doit pas (expliqué ci-dessous).

Mais cela ne signifie-t-il pas qu'il sera impossible de nettoyer les vieux déchets bien testés dont vous n'avez plus besoin? Oui, et c'est pourquoi vous devez être pragmatique à propos de ces choses. Il y a des situations où les règles doivent être enfreintes, mais pour votre intégration quotidienne typique, mon expérience montre que ces mesures sont très utiles. Ils donnent les deux implications suivantes.

  • Le code testable est promu. Lors de l'ajout de nouveau code, vous devez vraiment faire un effort pour rendre le code testable, car vous devrez essayer de tout couvrir avec vos cas de test. Le code testable est généralement une bonne chose.

  • La couverture des tests pour le code hérité augmente avec le temps. Lorsque vous ajoutez du nouveau code et que vous ne pouvez pas le couvrir avec un cas de test, vous pouvez essayer de couvrir un code hérité à la place pour contourner la règle LWM. Cette triche parfois nécessaire donne au moins l'effet secondaire positif que la couverture du code hérité augmentera avec le temps, ce qui rend l'application apparemment stricte de ces règles assez pragmatique dans la pratique.

Et encore une fois, si la boucle de rétroaction est trop longue, il pourrait être complètement impossible de configurer quelque chose comme ça dans le processus d'intégration.

Je voudrais également mentionner deux autres avantages généraux de la mesure de couverture du code.

  • L'analyse de couverture de code fait partie de l'analyse de code dynamique (par opposition à l'analyse statique, c'est-à-dire Lint). Les problèmes rencontrés lors de l'analyse de code dynamique (par des outils tels que la famille purify, http://www-03.ibm.com/software/products/en/rational-purify-family ) sont des choses comme les lectures de mémoire non initialisées (UMR), fuites de mémoire, etc. Ces problèmes ne peuvent être trouvés que si le code est couvert par un cas de test exécuté . Le code qui est le plus difficile à couvrir dans un cas de test est généralement les cas anormaux du système, mais si vous voulez que le système échoue gracieusement (c.-à-d. Trace d'erreur au lieu de planter), vous voudrez peut-être faire un effort pour couvrir les cas anormaux dans l'analyse de code dynamique également. Avec juste un peu de malchance, un UMR peut conduire à une faute de segment ou pire.

  • Les gens sont fiers de garder 100% pour le nouveau code, et les gens discutent des problèmes de test avec une passion similaire à d'autres problèmes d'implémentation. Comment cette fonction peut-elle être écrite de manière plus testable? Comment feriez-vous pour essayer de couvrir ce cas anormal, etc.

Et un négatif, pour être complet.

  • Dans un grand projet avec de nombreux développeurs impliqués, tout le monde ne sera certainement pas un génie du test. Certaines personnes ont tendance à utiliser la métrique de couverture du code comme preuve que le code est testé et cela est très loin de la vérité , comme mentionné dans de nombreuses autres réponses à cette question. C'est UNE métrique qui peut vous donner de bons avantages si elle est utilisée correctement, mais si elle est mal utilisée, elle peut en fait conduire à de mauvais tests. Mis à part les effets secondaires très précieux mentionnés ci-dessus, une ligne couverte montre uniquement que le système testé peut atteindre cette ligne pour certaines données d'entrée et qu'il peut s'exécuter sans se bloquer ni se bloquer.
Martin G
la source
7

Si c'était un monde parfait, 100% du code serait couvert par des tests unitaires. Cependant, comme ce n'est PAS un monde parfait, c'est une question de temps pour vous. En conséquence, je recommande de se concentrer moins sur un pourcentage spécifique et de se concentrer davantage sur les domaines critiques. Si votre code est bien écrit (ou au moins un fac-similé raisonnable de celui-ci), il devrait y avoir plusieurs points clés où les API sont exposées à un autre code.

Concentrez vos efforts de test sur ces API. Assurez-vous que les API sont 1) bien documentées et 2) que des cas de test écrits correspondent à la documentation. Si les résultats attendus ne correspondent pas aux documents, alors vous avez un bogue dans votre code, votre documentation ou vos cas de test. Tout cela est bon à examiner.

Bonne chance!

64BitBob
la source
6

De nombreux magasins n'évaluent pas les tests, donc si vous êtes au-dessus de zéro au moins, il y a une certaine appréciation de la valeur - donc sans doute non-nul n'est pas mauvais car beaucoup sont toujours nuls.

Dans le monde .Net, les gens citent souvent 80% comme raison. Mais ils disent cela au niveau de la solution. Je préfère mesurer au niveau du projet: 30% pourrait être bien pour le projet d'interface utilisateur si vous avez du sélénium, etc. ou des tests manuels, 20% pour le projet de couche de données pourrait être bien, mais 95% + pourrait être tout à fait réalisable pour l'entreprise couche de règles, si pas entièrement nécessaire. Ainsi, la couverture globale peut être, disons, de 60%, mais la logique métier critique peut être beaucoup plus élevée.

J'ai également entendu ceci: aspirer à 100% et vous atteindrez 80%; mais aspirez à 80% et vous atteindrez 40%.

En résumé: appliquez la règle 80:20 et laissez le nombre de bogues de votre application vous guider.

Greg Trevellick
la source
5

La couverture du code n'est qu'une autre mesure. En soi, il peut être très trompeur (voir www.thoughtworks.com/insights/blog/are-test-coverage-metrics-overrated ). Votre objectif ne doit donc pas être d'atteindre une couverture de code à 100% mais plutôt de vous assurer de tester tous les scénarios pertinents de votre application.

klementtt
la source
4

85% serait un bon point de départ pour les critères d'enregistrement.

J'aurais probablement choisi une variété de barres plus élevées pour les critères d'expédition - en fonction de la criticité des sous-systèmes / composants testés.

stephbu
la source
54
Comment êtes-vous arrivé à ce pourcentage?
sanity
En tant que note de bas de page - cela peut être compliqué pour les projets où l'automatisation est difficile - comme toujours pragmatique sur ce qui est réalisable par rapport à souhaitable.
stephbu le
4
Principalement par l'expérimentation. Il est assez facile d'obtenir une couverture de code à 80-90% pour les tests unitaires liés au développement - aller plus haut nécessite normalement une intervention de test divine - ou des chemins de code vraiment simples.
stephbu le
1
Je commence généralement par 1) les principaux chemins de code d'exécution 2) les cas d'exception évidents que je lance explicitement 3) les cas conditionnels qui se terminent par un "échec" Cela vous amène généralement dans la plage 70-80 Puis wackamole, bugs et régressions pour les cas d'angle, paramètre fuzzing etc. Refactoring pour permettre l'injection de méthodes etc. Je laisse généralement au moins autant de temps pour écrire / refactoring des tests liés aux développeurs que le code principal lui-même.
stephbu
4

J'utilise cobertura, et quel que soit le pourcentage, je recommanderais de maintenir à jour les valeurs de la tâche cobertura-check. Au minimum, continuez à augmenter la totalisation et la répartition totale juste en dessous de votre couverture actuelle, mais ne baissez jamais ces valeurs. Liez également la propriété Ant build failure à cette tâche. Si la construction échoue en raison d'un manque de couverture, vous connaissez le code ajouté de quelqu'un mais ne l'avez pas testé. Exemple:

<cobertura-check linerate="0"
                 branchrate="0"
                 totallinerate="70"
                 totalbranchrate="90"
                 failureproperty="build.failed" />
Gary Kephart
la source
4

Lorsque je pense que mon code n'est pas suffisamment testé à l'unité et que je ne sais pas quoi tester ensuite, j'utilise la couverture pour m'aider à décider quoi tester ensuite.

Si j'augmente la couverture dans un test unitaire - je sais que ce test unitaire vaut quelque chose.

Cela vaut pour le code qui n'est pas couvert, 50% couvert ou 97% couvert.

briqueteur
la source
3
Je suis complètement en désaccord. Un test unitaire ne vaut quelque chose que s'il y a une chance qu'il découvre un bogue (soit un bogue qui existe maintenant soit un bogue de régression à l'avenir); ou si cela aide à documenter le comportement de votre classe. Si une méthode est si simple qu'elle ne peut pas vraiment échouer, comme un getter à une ligne, alors il y a une valeur nulle pour lui fournir un test unitaire.
Dawood ibn Kareem
6
J'ai eu des bugs dans une ligne getters. D'après mon expérience, il n'y a pas de code sans bug. Aucune méthode ne peut vraiment échouer.
brickner
1
En supposant que votre getter d'une ligne est utilisé par un autre code que vous couvrez et que les tests de ce code réussissent, vous avez également indirectement couvert le getter d'une ligne. Si vous n'utilisez pas le getter, que fait-il dans votre code? Je suis d'accord avec David Wallace… il n'est pas nécessaire de tester directement les fonctions d'assistance simples qui sont utilisées ailleurs si le code et les tests qui dépendent de l'aide ne montrent pas qu'il pourrait y avoir un problème avec lui.
Lowell Montgomery du
@LowellMontgomery et que faire si le test de votre autre code échoue à cause de cet getter d'une ligne (qui n'a pas été testé)? S'il y avait un test en place pour le monoplace, il serait beaucoup plus facile de déterminer la cause de l'échec. Cela devient vraiment mauvais lorsque vous avez des centaines de doublures non testées utilisées à plusieurs endroits différents.
Daniel
L'hypothèse était que les tests utilisant le getter à une ligne ont réussi. S'il a échoué (par exemple, lorsque vous essayez d'utiliser la valeur de retour de votre getter à une ligne), vous pouvez le trier. Mais à moins qu'il n'y ait une raison vraiment pressante d'être si paranoïaque, vous devez tracer la ligne quelque part. D'après mon expérience, j'ai besoin de prioriser ce qui me fait perdre mon temps et mon attention et les "getters" (qui fonctionnent) vraiment simples n'ont pas besoin de tests séparés. Ce temps peut être consacré à l'amélioration d'autres tests ou à une couverture plus complète du code qui est plus susceptible d'échouer. (c'est-à-dire que je maintiens ma position d'origine, avec David Wallace).
Lowell Montgomery du
4

Je préfère faire BDD, qui utilise une combinaison de tests d'acceptation automatisés, éventuellement d'autres tests d'intégration et des tests unitaires. La question pour moi est de savoir quelle devrait être la couverture cible de la suite de tests automatisée dans son ensemble.

Cela mis à part, la réponse dépend de votre méthodologie, de votre langue et de vos outils de test et de couverture. Lorsque vous effectuez TDD en Ruby ou Python, il n'est pas difficile de maintenir une couverture à 100%, et cela en vaut la peine. Il est beaucoup plus facile de gérer une couverture à 100% qu'une couverture à 90%. Autrement dit, il est beaucoup plus facile de combler les lacunes de couverture au fur et à mesure qu'elles apparaissent (et lorsque vous faites bien le TDD, les lacunes de couverture sont rares et valent généralement la peine) que de gérer une liste des lacunes de couverture que vous n'avez pas pu contourner et que vous manquez de couverture. régressions dues à votre arrière-plan constant de code découvert.

La réponse dépend également de l'historique de votre projet. Je n'ai trouvé que ce qui précède pratique dans les projets gérés de cette façon depuis le début. J'ai considérablement amélioré la couverture des grands projets hérités, et cela en valait la peine, mais je n'ai jamais trouvé pratique de revenir en arrière et de combler toutes les lacunes de couverture, car l'ancien code non testé n'est pas suffisamment bien compris pour le faire correctement et rapidement.

Dave Schweisguth
la source
3

Si vous effectuez des tests unitaires depuis un bon moment, je ne vois aucune raison pour que cela n'approche pas de 95% +. Cependant, au minimum, j'ai toujours travaillé avec 80%, même lorsqu'il était nouveau dans les tests.

Ce nombre ne doit inclure que du code écrit dans le projet (exclut les frameworks, plugins, etc.) et peut-être même exclut certaines classes composées entièrement de code écrit d'appels à du code extérieur. Ce type d'appel doit être moqué / tronqué.

Tony Pitale
la source
3

De manière générale, parmi les nombreux articles sur les meilleures pratiques en matière d'excellence en ingénierie que j'ai lus, 80% pour le nouveau code dans les tests unitaires est le point qui donne le meilleur rendement. Aller au-dessus de ce CC% donne une quantité inférieure de défauts pour la quantité d'effort exercée. Il s'agit d'une meilleure pratique utilisée par de nombreuses grandes sociétés.

Malheureusement, la plupart de ces résultats sont internes aux entreprises, il n'y a donc pas de littérature publique sur laquelle je puisse vous indiquer.

user17222
la source
3

La couverture du code est excellente, mais seulement tant que les avantages que vous en retirez l'emportent sur le coût / l'effort de sa réalisation.

Nous travaillons à une norme de 80% depuis un certain temps, mais nous venons de prendre la décision de l'abandonner et de nous concentrer davantage sur nos tests. Se concentrer sur la logique métier complexe, etc.,

Cette décision a été prise en raison du temps croissant que nous avons passé à rechercher la couverture du code et à maintenir les tests unitaires existants. Nous pensions que nous étions arrivés au point où l'avantage que nous obtenions de notre couverture de code était jugé inférieur à l'effort que nous devions déployer pour y parvenir.

Simon Keep
la source
2

Réponse courte: 60-80%

Réponse longue: je pense que cela dépend totalement de la nature de votre projet. Je commence généralement un projet en testant à l'unité chaque pièce pratique. À la première "version" du projet, vous devriez avoir un assez bon pourcentage de base basé sur le type de programmation que vous faites. À ce stade, vous pouvez commencer à «appliquer» une couverture de code minimale.

user11087
la source
2

Découvrez Crap4j . C'est une approche légèrement plus sophistiquée que la couverture de code simple. Il combine des mesures de couverture de code avec des mesures de complexité, puis vous montre quel code complexe n'est pas actuellement testé.

Don Kirkby
la source
2

Ma réponse à cette énigme est d'avoir une couverture en ligne de 100% du code que vous pouvez tester et une couverture en ligne de 0% du code que vous ne pouvez pas tester.

Ma pratique actuelle en Python consiste à diviser mes modules .py en deux dossiers: app1 / et app2 / et lors de l'exécution des tests unitaires, calculer la couverture de ces deux dossiers et vérifier visuellement (je dois automatiser cela un jour) que app1 a une couverture de 100% et app2 a une couverture de 0%.

Lorsque / si je trouve que ces chiffres diffèrent de la norme, j'étudie et modifie la conception du code afin que la couverture soit conforme à la norme.

Cela signifie que je peux recommander d'atteindre une couverture de ligne à 100% du code de la bibliothèque.

Je passe également en revue de temps en temps app2 / pour voir si je pouvais tester n'importe quel code là-bas, et si je peux le déplacer dans app1 /

Maintenant, je ne suis pas trop inquiet de la couverture globale car cela peut varier énormément en fonction de la taille du projet, mais en général, j'ai vu 70% à plus de 90%.

Avec python, je devrais être en mesure de concevoir un test de fumée qui pourrait exécuter automatiquement mon application tout en mesurant la couverture et, espérons-le, obtenir un agrégat de 100% en combinant le test de fumée avec des chiffres les plus faibles.

quamrana
la source
2

Voir la couverture sous un autre angle: un code bien écrit avec un flux de contrôle clair est le plus facile à couvrir, le plus facile à lire et généralement le moins buggé. En écrivant le code avec la clarté et la couvrabilité à l'esprit, et en écrivant les tests unitaires en parallèle avec le code, vous obtenez les meilleurs résultats à mon humble avis.


la source
2

À mon avis, la réponse est "Cela dépend du temps dont vous disposez". J'essaie d'atteindre 100% mais je ne fais pas d'histoires si je ne l'obtiens pas avec le temps dont je dispose.

Lorsque j'écris des tests unitaires, je porte un chapeau différent de celui que je porte lors du développement du code de production. Je pense à ce que le code testé prétend faire et quelles sont les situations qui peuvent le casser.

Je respecte généralement les critères ou règles suivants:

  1. Que le test unitaire devrait être une forme de documentation sur le comportement attendu de mes codes, c'est-à-dire. la sortie attendue étant donnée une certaine entrée et les exceptions qu'elle peut lever que les clients peuvent vouloir attraper (ce que les utilisateurs de mon code devraient savoir?)

  2. Que le test unitaire devrait m'aider à découvrir les conditions que je n'aurais peut-être pas encore imaginées. (Comment rendre mon code stable et robuste?)

Si ces deux règles ne produisent pas une couverture à 100%, qu'il en soit ainsi. Mais une fois, j'ai le temps, j'analyse les blocs et les lignes découverts et détermine s'il y a encore des cas de test sans tests unitaires ou si le code doit être refactorisé pour éliminer les codes inutiles.

Mark Menchavez
la source
1

Cela dépend beaucoup de votre application. Par exemple, certaines applications se composent principalement de code GUI qui ne peut pas être testé à l'unité.

Thomas
la source
5
Vous devriez probablement utiliser Model View Presenter pour votre interface utilisateur si vous êtes dans un environnement TDD.
Charles Graham
1

Je ne pense pas qu'il puisse y avoir une telle règle N / B.
Le code doit être révisé, en accordant une attention particulière aux détails critiques.
Cependant, s'il n'a pas été testé, il a un bug!

Nescio
la source
Vous ne voulez pas de règle, il vous suffit de nous faire part de vos retours d'expérience sur la corrélation entre le pourcentage de couverture du code et l'efficacité des tests unitaires.
sanity
1

Selon la criticité du code, entre 75% et 85% est une bonne règle de base. Le code d'expédition doit certainement être testé de manière plus approfondie que dans les services publics, etc.

William Keller
la source
1

Cela doit dépendre de la phase du cycle de vie de développement de votre application dans laquelle vous vous trouvez.

Si vous êtes au développement depuis un certain temps et que vous avez déjà beaucoup de code implémenté et que vous réalisez maintenant que vous devez penser à la couverture du code, vous devez vérifier votre couverture actuelle (si elle existe), puis utiliser cette ligne de base pour définir des jalons à chaque sprint (ou une augmentation moyenne sur une période de sprints), ce qui signifie assumer la dette de code tout en continuant à fournir de la valeur à l'utilisateur final (du moins d'après mon expérience, l'utilisateur final ne se soucie pas du tout si vous avez augmenté le test couverture s'ils ne voient pas de nouvelles fonctionnalités).

Selon votre domaine, il n'est pas déraisonnable de viser 95%, mais je dois dire qu'en moyenne, vous allez examiner un cas moyen de 85% à 90%.

codeLes
la source
1

Je pense que le meilleur symptôme d'une couverture de code correcte est que la quantité de problèmes concrets que les tests unitaires aident à résoudre correspond raisonnablement à la taille du code de tests unitaires que vous avez créé.

dimarzioniste
la source
1

Je pense que ce qui importe le plus, c'est de savoir quelle est la tendance de la couverture au fil du temps et de comprendre les raisons des changements dans la tendance. Que vous considériez les changements de tendance comme bons ou mauvais dépendra de votre analyse de la raison.

Rob Scott
la source
0

Nous visions> 80% jusqu'à il y a quelques jours, mais après avoir utilisé beaucoup de code généré, nous ne nous soucions pas du pourcentage d'âge, mais faisons en sorte que le réviseur prenne un appel sur la couverture requise.

reva
la source
0

D'après la publication de Testivus, je pense que le contexte de réponse devrait être le deuxième programmeur. Cela dit, d'un point de vue pratique, nous avons besoin de paramètres / objectifs à atteindre. Je considère que cela peut être "testé" dans un processus Agile en analysant le code dont nous avons l'architecture, les fonctionnalités (user stories), puis en arriver à un certain nombre. Sur la base de mon expérience dans le domaine des télécommunications, je dirais que 60% est une bonne valeur à vérifier.

D Lovece
la source