web-dev-qa-db-fra.com

Une différence entre la couverture des relevés et des décisions

Couverture d'instruction est censé s'assurer que chaque instruction du code est exécutée au moins une fois.
Décision/couverture de branche est censé vérifier que chaque branche/sortie d’une décision est testée, c’est-à-dire que toutes les instructions dans les deux branches faux/vrai seront exécutées.
Mais n'est-ce pas la même chose? Dans la couverture des instructions, je dois exécuter toutes les instructions. Je suppose que cela ne peut se faire qu'en exécutant tous les moyens possibles. Je sais qu'il me manque quelque chose ici ..

19
John V

Si les tests ont une couverture complète des branches, nous pouvons dire que la couverture des relevés est complète , mais pas l'inverse.

Couverture de 100% des succursales => Couverture des relevés de 100%

La couverture des relevés à 100% n'implique pas une couverture à 100% des succursales

la raison étant dans la couverture des branches en dehors de l'exécution de toutes les instructions, nous devons également vérifier si les tests exécutent toutes les branches, ce qui peut être interprété comme couvrant toutes les arêtes de la branche de flux de contrôle.

if(a){
   if(b){
     bool statement1 = true;
   }
}

a = true, b = true donnera une couverture de relevé de 100%, mais pas une couverture de branche

 enter image description here

Dans la couverture de branche, nous devons couvrir tous les bords , ce qui nous manquait dans la couverture de relevé représentée par lignes rouges dans l'image ci-dessus.

8
murali krish

La réponse de Paul n'est pas tout à fait juste, du moins je le pense (selon les définitions de l'ISTQB). Il existe une différence assez significative entre la couverture des relevés, des décisions/branches et des conditions. J'utiliserai l'exemple de l'autre réponse mais je le modifierai un peu pour pouvoir montrer les trois exemples de couverture de test. Les tests écrits ici donnent une couverture de 100% des tests pour chaque type.

if(a || b)) {
    test1 = true;
}
else {
    if(c) {
      test2 = true
    }
}

Nous avons deux déclarations ici - si (a || b) et si (c), pour expliquer pleinement ces différences de couverture:

  1. couverture de la déclaration doit tester chaque déclaration au moins une fois; il suffit donc de deux tests:
    • a = true b = false - cela nous donne le chemin si (a || b) true -> test1 = true
    • a = false, b = false et c = true - cela nous donne le chemin: if (a || b) false -> else -> if (c) -> test2 = true.

De cette façon, nous avons exécuté chaque déclaration.

  1. couverture de la branche/de la décision nécessite encore un test:

    • a = false, b = false, c = false - cela nous mène à cette seconde si, mais nous exécutons une fausse branche à partir de cette instruction, celle-ci n'a pas été exécutée dans la couverture des instructions 

    De cette façon, nous avons testé toutes les branches, ce qui signifie que nous avons suivi tous les chemins.

  2. couverture de la condition nécessite un autre test:

    • a = false, b = true - conduit par le même chemin que le premier test mais exécute l'autre décision dans l'instruction OR (a || b) pour l'exécuter.

De cette façon, toutes les conditions sont testées, ce qui signifie que nous avons parcouru tous les chemins (branches) et les avons déclenchées avec chaque condition possible. La première instruction 'if' était vraie dans le premier test, car a = true l'a déclenchée et dans le dernier test, car b = true l'a déclenché. Bien sûr, quelqu'un peut dire que les cas avec a = true et b = true doivent également être testés, mais lorsque nous vérifierons comment «ou» fonctionne, nous pouvons voir que ce n'est pas nécessaire et que la variable c peut également être de n'importe quelle valeur. dans ces tests, il n'est pas évalué.

Au moins je l'ai interprété de cette façon. Si quelqu'un est toujours intéressé :)

EDIT: Dans la plupart des sources que j'ai trouvées récemment, les termes de décision/couverture de branche sont équivalents et le terme que je décris comme couverture de décision est en fait une couverture de condition d'où la mise à jour de la réponse.

32
Faflok

Vous pouvez avoir une déclaration comme:

if(a || b || (c && d && !e)) {
    test1 = true;
} else {
    test2 = false;
}

Si votre couverture de code indique que les lignes test1 et test2 sont touchées, vous avez une couverture de relevé, mais pour obtenir une couverture complète de branche, vous devez tester si a est vrai, quand a est faux mais b est vrai, quand a et b sont faux mais c et d sont vrais et e est faux, etc.

La couverture des branches couvre toutes les combinaisons possibles de choix de branches et est donc plus difficile à atteindre à 100%. 

3
Paul Rutland

Bonne question. L’explication que j’utilise souvent est qu’une instruction if sans branche d’autre a toujours une instruction else «vide» invisible:

  • La couverture des déclarations simples insiste simplement sur le fait que toutes les déclarations qui y figurent sont réellement exécutées.

  • La couverture de branche insiste sur le fait que même des branches invisibles sont exécutées.

Des situations similaires se produisent avec des instructions switch sans casse par défaut et des boucles de répétition jusqu'à. La couverture de branche nécessite l'exécution d'un cas par défaut et l'exécution d'un jusqu'à-répéter au moins deux fois.

Un exemple de code:

if (passwordEnteredOK()) {
    enterSystem();
} 
/* Invisible else part 
else {
  // do nothing
}
*/

Avec la couverture des relevés, il vous suffit de vérifier qu'avec un mot de passe correct, vous pouvez utiliser le système. Avec la couverture de branche, vous vérifiez également qu'avec un mot de passe incorrect, vous allez pas entrer dans le système.

1
avandeursen