J'ai un morceau de code qui ressemble à ceci:
function bool PassesBusinessRules()
{
bool meetsBusinessRules = false;
if (PassesBusinessRule1
&& PassesBusinessRule2
&& PassesBusinessRule3)
{
meetsBusinessRules= true;
}
return meetsBusinessRules;
}
Je pense qu'il devrait y avoir quatre tests unitaires pour cette fonction particulière. Trois pour tester chacune des conditions dans l'instruction if et s'assurer qu'elle retourne false. Et un autre test qui s'assure que la fonction retourne vrai.
Question: Devrait-il y avoir à la place dix tests unitaires? Neuf qui vérifie chacun des chemins d'échec possibles. C'EST À DIRE:
- Faux Faux Faux
- Faux Faux Vrai
- Faux Vrai Faux
Et ainsi de suite pour chaque combinaison possible.
Je pense que c'est exagéré, mais certains des autres membres de mon équipe ne le font pas. La façon dont je le vois est que si BusinessRule1 échoue, il devrait toujours retourner faux, peu importe si elle a été vérifiée en premier ou en dernier.
unit-testing
bwalk2895
la source
la source
Réponses:
Officiellement, ces types de couverture ont des noms.
Tout d'abord, il existe une couverture de prédicat : vous voulez avoir un scénario de test qui rend l'instruction if vraie et une qui la rend fausse. Le respect de cette couverture est probablement une exigence de base pour une bonne suite de tests.
Ensuite, il y a la couverture des conditions : ici, vous voulez tester que chaque sous-condition dans le if a la valeur true et false. Cela crée évidemment plus de tests, mais il détecte généralement plus de bogues, donc c'est souvent une bonne idée d'inclure dans votre suite de tests si vous en avez le temps.
Les critères de couverture les plus avancés sont généralement appelés couverture des conditions combinatoires : ici, l'objectif est d'avoir un cas de test qui passe par toutes les combinaisons possibles de valeurs booléennes dans votre test.
Est-ce mieux qu'une simple couverture de prédicat ou de condition? En termes de couverture, bien sûr. Mais ce n'est pas gratuit. Il s'agit d'un coût très élevé pour la maintenance des tests. Pour cette raison, la plupart des gens ne se soucient pas d'une couverture combinatoire complète. En général, tester toutes les branches (ou toutes les conditions) sera suffisant pour détecter les bugs. L'ajout de tests supplémentaires pour les tests combinatoires n'attrapera généralement pas plus de bugs, mais nécessite beaucoup d'efforts pour créer et maintenir. L'effort supplémentaire fait généralement que cela ne vaut pas le très petit gain, donc je ne recommanderais pas cela.
Une partie de cette décision devrait être basée sur le degré de risque que vous pensez que ce code sera. S'il a beaucoup de place pour échouer, cela vaut la peine d'être testé. S'il est quelque peu stable et ne changera pas grand-chose, vous devriez envisager de concentrer vos efforts de test ailleurs.
la source
En fin de compte, cela dépend de vous (équipe r), du code et de l'environnement spécifique du projet. Il n'y a pas de règle universelle. Vous (l'équipe r) devez écrire autant de tests que vous le souhaitez pour vous assurer que le code est bien correct . Donc, si vos coéquipiers ne sont pas convaincus par 4 tests, vous en aurez peut-être besoin de plus.
OTOH temps pour écrire des tests unitaires est généralement une ressource rare. Essayez donc de trouver la meilleure façon de passer le temps limité dont vous disposez . Par exemple, si vous avez une autre méthode importante avec une couverture de 0%, il peut être préférable d'écrire quelques tests unitaires pour couvrir celle-ci, plutôt que d'ajouter des tests supplémentaires pour cette méthode. Bien sûr, cela dépend aussi de la fragilité de la mise en œuvre de chacun. La planification de nombreux changements à cette méthode particulière dans un avenir prévisible peut justifier une couverture supplémentaire des tests unitaires. Il en va de même pour le chemin critique à l'intérieur du programme. Ce sont tous des facteurs que vous seul (l'équipe r) pouvez évaluer.
Personnellement, je serais généralement satisfait des 4 tests que vous décrivez, à savoir:
plus peut-être un:
pour s'assurer que la seule façon d'obtenir une valeur de retour
true
est de satisfaire aux 3 règles de gestion. Mais au final, si vos coéquipiers insistent pour que les chemins combinatoires soient couverts, il peut être moins cher d'ajouter ces tests supplémentaires que de continuer l'argument beaucoup plus longtemps :-)la source
Si vous voulez être sûr, vous aurez besoin de huit tests unitaires en utilisant les conditions représentées par une table de vérité à trois variables ( http://teach.valdosta.edu/plmoch/MATH4161/Spring%202004/and_or_if_files/image006.gif ).
Vous ne pouvez jamais être sûr que la logique métier stipulera toujours que les vérifications sont effectuées dans cet ordre et vous voulez que le test connaisse le moins possible la mise en œuvre réelle.
la source
Oui, il devrait y avoir la combinaison complète dans un monde idéal.
Lorsque vous effectuez le test unitaire, vous devez vraiment essayer d'ignorer comment la méthode fait son travail. Fournissez simplement les 3 entrées et vérifiez que la sortie est correcte.
la source
L'État est mauvais. La fonction suivante n'a pas besoin d'un test unitaire car elle n'a pas d'effets secondaires et il est bien compris ce qu'elle fait et ce qu'elle ne fait pas. Pourquoi le tester? Ne fais-tu pas confiance à ton propre cerveau ??? Les fonctions statiques sont super!
la source
a
,b
etc
. Vous pouvez déplacer la logique métier comme vous le souhaitez, au final, vous devez toujours la tester quelque part.Je sais que cette question est assez ancienne. Mais je veux donner une autre perspective au problème.
Tout d'abord, vos tests unitaires devraient avoir deux objectifs:
what's the class' intention
ethow the class is doing its work
Donc, en récapitulant le problème, nous voulons tester a
complex if statement
, pour l'exemple donné, il y a 2 ^ 3 possibilités, c'est une quantité importante de tests que nous pouvons écrire.what is doing the code
En revanche, si vous êtes dans la position que vos tests sont encore plus complexes que l'implémentation, c'est parce que l'implémentation doit être repensée (plus ou moins selon les cas) plutôt que le test lui-même.
Pour les instructions if complexes, par exemple, vous pouvez penser au modèle de responsabilité de chaîne , implémentant chaque gestionnaire de cette façon:
If some simple business rule apply, derive to the next handler
Dans quelle mesure serait-il simple de tester diverses règles simples au lieu d'une règle complexe?
J'espère que ça aide,
la source
C'est l'un de ces cas où quelque chose comme quickcheck ( http://en.wikipedia.org/wiki/QuickCheck ) sera votre ami. Au lieu d'écrire tous les N cas à la main, l'ordinateur doit générer tous (ou au moins un grand nombre) de cas de test possibles et valider que tous renvoient un résultat sensible.
Nous programmons des ordinateurs pour vivre ici, pourquoi ne pas programmer l'ordinateur pour générer vos cas de test pour vous?
la source
Vous pouvez transformer les conditions en conditions de garde:
Je ne pense pas que cela réduit le nombre de cas, mais mon expérience est qu'il est plus facile de les répartir de cette façon.
(Notez que je suis un grand fan de "point de sortie unique", mais je fais une exception pour les conditions de garde. Mais il existe d'autres façons de structurer le code afin que vous n'ayez pas de retours séparés.)
la source