J'ai pensé que j'ajouterais quatre autres cas, où Debug.Assert peut être le bon choix.
1) Quelque chose que je n'ai pas vu mentionné ici est la couverture conceptuelle supplémentaire que les Asserts peuvent fournir pendant les tests automatisés . Comme exemple simple:
Lorsqu'un appelant de niveau supérieur est modifié par un auteur qui pense avoir étendu la portée du code pour gérer des scénarios supplémentaires, idéalement (!) Ils écriront des tests unitaires pour couvrir cette nouvelle condition. Il se peut alors que le code entièrement intégré semble fonctionner correctement.
Cependant, en réalité, une faille subtile a été introduite, mais non détectée dans les résultats des tests. Le non est devenu callee déterministe dans ce cas, et seulement arrive à donner le résultat escompté. Ou peut-être qu'il a produit une erreur d'arrondi qui n'a pas été remarquée. Ou a provoqué une erreur qui a été compensée également ailleurs. Ou accordé non seulement l'accès demandé mais des privilèges supplémentaires qui ne devraient pas être accordés. Etc.
À ce stade, les instructions Debug.Assert () contenues dans l'appelé couplées au nouveau cas (ou cas de bord) entraîné par des tests unitaires peuvent fournir une notification inestimable pendant le test que les hypothèses de l'auteur d'origine ont été invalidées, et le code ne doit pas être publié sans examen supplémentaire. Les assertions avec tests unitaires sont les partenaires parfaits.
2) De plus, certains tests sont simples à écrire, mais coûteux et inutiles compte tenu des hypothèses initiales . Par exemple:
Si un objet n'est accessible qu'à partir d'un certain point d'entrée sécurisé, une requête supplémentaire doit-elle être effectuée dans une base de données de droits réseau à partir de chaque méthode d'objet pour garantir que l'appelant dispose des autorisations? Sûrement pas. Peut-être que la solution idéale comprend la mise en cache ou une autre extension des fonctionnalités, mais la conception ne l'exige pas. Un Debug.Assert () affichera immédiatement lorsque l'objet a été attaché à un point d'entrée non sécurisé.
3) Ensuite, dans certains cas, votre produit peut n'avoir aucune interaction de diagnostic utile pour tout ou partie de ses opérations lorsqu'il est déployé en mode de publication . Par exemple:
Supposons qu'il s'agisse d'un périphérique embarqué en temps réel. Lancer des exceptions et redémarrer lorsqu'il rencontre un paquet mal formé est contre-productif. Au lieu de cela, l'appareil peut bénéficier d'un fonctionnement au meilleur effort, même au point de rendre du bruit dans sa sortie. Il peut également ne pas avoir d'interface humaine, de périphérique de journalisation ou même être physiquement accessible par l'homme lorsqu'il est déployé en mode de publication, et la sensibilisation aux erreurs est mieux fournie en évaluant la même sortie. Dans ce cas, les assertions libérales et les tests de pré-publication approfondis sont plus précieux que les exceptions.
4) Enfin, certains tests sont inutiles uniquement parce que l'appelé est perçu comme extrêmement fiable . Dans la plupart des cas, plus le code est réutilisable, plus l'effort a été mis pour le rendre fiable. Par conséquent, il est courant d'exceptionner les paramètres inattendus des appelants, mais d'assert pour les résultats inattendus des appels. Par exemple:
Si une String.Find
opération principale indique qu'elle renverra un -1
lorsque les critères de recherche ne sont pas trouvés, vous pourrez peut-être effectuer en toute sécurité une opération plutôt que trois. Cependant, s'il est effectivement retourné -2
, vous n'aurez peut-être aucun plan d'action raisonnable. Il ne serait pas utile de remplacer le calcul plus simple par un calcul qui teste séparément une -1
valeur, et déraisonnable dans la plupart des environnements de versions pour surcharger votre code de tests garantissant que les bibliothèques principales fonctionnent comme prévu. Dans ce cas, les assertions sont idéales.