10
votes

Comment tester le code qui ne devrait jamais être exécuté?

La méthode suivante ne doit être appelée que si elle a été vérifiée selon laquelle il existe des chiffres non valides (en appelant une autre méthode). Comment puis-je tester - couvrir le lancer code> -line dans l'extrait suivant? Je sais que une manière pourrait être de fusionner le vérifiant VerifyTherareReInvaliDigits code> et cette méthode. Je cherche d'autres idées.

public int FirstInvalidDigitPosition {
    get {
        for (int index = 0; index < this.positions.Count; ++index) {
            if (!this.positions[index].Valid) return index;
        }
        throw new InvalidOperationException("Attempt to get invalid digit position whene there are no invalid digits.");
    }
}


1 commentaires

Le simple fait que vous dites que cela ne devrait pas être exécuté et que vous ne puissiez pas être atteint me dit "supprimer". Vous avez validé la chaîne comme invalide pour arriver ici, vous savez donc que la propriété reviendra quelque chose.


5 Réponses :


22
votes

Si l'instruction "Jet" en question est vraiment inaccessible em> sous tout scénario possible, il devrait être supprimé em> et remplacé par: xxx pré> Si le code est accessible, écrivez un test unitaire qui teste ce scénario. Les scénarios de reporting d'erreur pour les méthodes accessibles aux normes sont des scénarios parfaitement valides. Vous devez gérer toutes les entrées correctement, même les entrées mauvaises. Si la bonne chose à faire est de lancer une exception, testez-vous que vous lancez une exception. P>

mise à jour: selon les commentaires, il est en fait impossible pour l'erreur d'être touché et que le code est donc inaccessible. Mais maintenant, le débog.fail n'est pas accessible non plus, et cela ne compile pas car le compilateur note qu'une méthode qui renvoie une valeur a un point d'extrémité accessible. P>

Le premier problème ne doit pas être un problème ; L'outil de couverture de code doit sûrement être configurable pour ignorer le code sans précédent uniquement de débogage. Mais les deux problèmes peuvent être résolus en réécrivant la boucle: P>

public int? FirstInvalidDigitPosition { 
    get { 
        for (int index = 0; index < this.positions.Count; ++index) { 
            if (!this.positions[index].Valid) return index; 
        } 
        return null;
    } 
} 


4 commentaires

J'aurais dû mentionner, je fais du TDD, qui m'exempte de tester les faux cas: P C'est une méthode de classe-public, mais de module-interne. Ainsi, jeter une exception ne fait pas partie de l'exigence, d'aucun test.


Aussi, déboguer.fail ne sera toujours pas couvert de code, remplaçant également ce lancer avec debug.fail est une erreur de compilation.


Si Jon Skeet a posté exactement la même réponse, il aurait dû avoir 4 fois plus de votes à jour. N'est pas si fabuleux?


Oh, pourquoi ne pas c # a une exception de devoir?



4
votes

Je ne comprends pas pourquoi vous ne voudriez pas écrire un test de l'unité qui exerce un "code qui ne devrait pas arriver".

S'il "ne devrait pas arriver", alors pourquoi écrivez-vous le code du tout? Parce que vous pensez que cela pourrait arriver, peut-être une erreur dans un futur refactoring enfreindra votre autre validation et ce code sera exécuté.

Si vous pensez que cela vaut la peine d'être écrit le code, cela vaut la peine de le tester.


4 commentaires

Je suis d'accord - écrire du code qui "ne doit jamais être exécuté" sonne comme un exercice assez gaspillé pour moi.


bon point. J'écris ce code parce que c # nécessite une méthode non liée à la fin avec le retour ou le lancer. Je préférerais préférer une exception de lancement de temps d'exécution au moment de l'exécution. Donc, je n'ai pas à écrire cette ligne laid. Ce qui signifie que j'ai besoin d'une solution de contournement pour la fonction de langue ou trouvez une faille dans la conception.


Pour améliorer la conception, j'utiliserais une méthode plutôt qu'une propriété. Une propriété "looke" comme un simple accès de la variable de membre à l'appelant, il est donc probable qu'elles seront surpris si cela prend beaucoup de temps à exécuter, a des effets secondaires (comme changer les variables de membre dans un "get 'Appel), provoque le déclenchement des événements ou une exception. D'autre part, il est normal d'une méthode de retour d'une valeur pour indiquer "non trouvé" (par exemple. -1, comme string.indexof) ou lancer une exception - donc une méthode est un bien meilleur choix de conception.


Je pense que la question est que vous ne voulez pas supposer que c'est littéralement impossible d'y arriver, mais en même temps, vous ne pouvez tout simplement pas y arriver à partir d'un test. Ce n'est pas que vous ne voulez pas le tester, c'est qu'il n'y a pas de moyen «normal» d'y arriver.



3
votes

Une partie du but de tester est de tester les deux choses qui devraient se produire et des choses qui peuvent se produire.

Si vous avez du code qui devrait < / EM> Ne jamais exécuter, mais pourrait sous les conditions de droite (ou incorrectes), vous pouvez vérifier que l'exception se produit dans les bonnes conditions (dans la structure de test d'unité de MS) en décorant votre méthode de test avec: < / p> xxx


2 commentaires

Je fais TDD, en tant que tel, je ne teste pas pour des choses qui peuvent mais jamais devraient arriver. Dans ce cas, l'exception est une indication d'un bogue dans le code et non une condition exceptionnelle.


un moyen de rédiger ce que vous avez écrit, c'est qu'il y a des choses que vous savez peut arriver, mais vous ne faites rien! Puisque je ne pense pas que vous souhaitiez laisser votre programme ouvert au comportement non défini, vous voudrez peut-être réfléchir à votre stratégie de test et de codage d'autres! Autant que possible, vos exigences devraient être de traiter de manière satisfaisante avec toutes les intrants possibles, incluez-les indésirables. Écrivez des tests pour vérifier que votre programme répond à ces exigences.



4
votes

Il est parfois nécessaire d'écrire de petits bits de code qui ne peuvent pas exécuter, juste pour apaiser un compilateur (par exemple, si une fonction qui jette toujours une exception, sort de l'application, etc. est appelée à partir d'une fonction qui est censée revenir une valeur, le compilateur peut insister sur le fait que l'appelant comprend un "retour 0" "," Renvoie "Rien", etc. Déclaration qui ne peut jamais exécuter. Je ne penserais pas qu'il faut être nécessaire pour tester un tel "code", car il peut être impossible de le faire exécuter sans briser sérieusement d'autres parties du système.

Une question plus intéressante vient avec le code que le processeur ne devrait jamais être en mesure d'exécuter dans des circonstances normales, mais qui existe pour minimiser les dommages des circonstances anormales. Par exemple, certaines applications critiques de sécurité que j'ai écrites commencées par code quelque chose comme (application réelle est le code de la machine; donné ci-dessous est pseudo-code) xxx

Je ne sais pas comment exactement on irait à la question de tester ce code dans l'affaire de défaillance. Le but du code est de s'assurer que si le registre a subi des dommages électrostatiques ou autres, sinon ne fonctionne pas, le système sera éteint en toute sécurité. Absent un équipement très fantaisie, cependant, je ne sais pas comment tester ce code.


0 commentaires

0
votes

Pour reformuler la question, essentiellement: comment testez-vous un état invalide de votre système lorsque vous avez déjà eu beaucoup de problèmes pour vous assurer que le système ne peut pas entrer dans cet état non valide en premier lieu?

Il fera des tests légèrement plus lents, mais je suggérerai d'utiliser la réflexion pour mettre votre système dans l'état non valide afin de le tester.

remarquez également que la réflexion est précisément l'une des voies possibles pour votre système pour entrer dans cet état non valide, qui exécutera votre soi-disant impossible à atteindre le code.

Si votre code était vraiment impossible à atteindre, ce qui n'est pas tout au cas dans votre exemple aussi loin que je vois, Ensuite, vous devriez supprimer le code. Par exemple: xxx

Je ne voudrais pas non plus écrire un test de l'unité qui exerce un code qui ne doit jamais être exécuté.

Que voulez-vous dire par "devrait" ici? Comme, que doit ne pas être exécuté? Il devrait sûrement être ok pour que le code soit exécuté dans un test . Il doit être exécuté dans un test.


0 commentaires