J'ai un tas de classes qui traitent de la validation des valeurs. Par exemple, une RangeValidator
classe vérifie si une valeur se situe dans la plage spécifiée.
Chaque classe de validateur contient deux méthodes is_valid(value)
:, qui renvoie True
ou en False
fonction de la valeur, et ensure_valid(value)
qui vérifie une valeur spécifiée et soit ne fait rien si la valeur est valide, ou lève une exception spécifique si la valeur ne correspond pas aux règles prédéfinies.
Il existe actuellement deux tests unitaires associés à cette méthode:
Celui qui transmet une valeur non valide et garantit que l'exception a été levée.
def test_outside_range(self): with self.assertRaises(demo.ValidationException): demo.RangeValidator(0, 100).ensure_valid(-5)
Celui qui passe une valeur valide.
def test_in_range(self): demo.RangeValidator(0, 100).ensure_valid(25)
Bien que le deuxième test fasse son travail - échoue si l'exception est levée et réussit s'il ensure_valid
ne lance rien - le fait qu'il n'y ait pas de assert
s à l'intérieur semble étrange. Quelqu'un qui lit un tel code se demanderait immédiatement pourquoi il existe un test qui semble ne rien faire.
Est-ce une pratique courante lors du test de méthodes qui ne renvoient pas de valeur et n'ont pas d'effets secondaires? Ou dois-je réécrire le test d'une manière différente? Ou simplement mettre un commentaire expliquant ce que je fais?
la source
self
référence) et ne renvoie aucun résultat, ce n'est pas une fonction pure.void
dans de nombreuses langues et a des règles stupides.) Alternativement, vous pouvez avoir une infinité boucle (qui fonctionne même lorsque "ne renvoie aucun résultat" signifie vraiment ne renvoie aucun résultat.unit -> unit
dans n'importe quelle langue qui considère l'unité comme un type de données standard au lieu de quelque chose de magique. Malheureusement, il retourne juste l'unité et ne fait rien d'autre.Réponses:
La plupart des frameworks de test ont une assertion explicite pour "ne lance pas", par exemple Jasmine a
expect(() => {}).not.toThrow();
et nUnit et ses amis en ont également un.la source
Cela dépend fortement du langage et du framework utilisés. En termes de
NUnit
, il existe desAssert.Throws(...)
méthodes. Vous pouvez leur passer une méthode lambda:qui est exécuté dans le
Assert.Throws
. L'appel au lambda sera très probablement encapsulé par untry { } catch { }
bloc et l'assertion échouera, si une exception est interceptée.Si votre framework ne fournit pas ces moyens, vous pouvez le contourner en encapsulant l'appel par vous-même (j'écris en C #):
Cela rend l'intention plus claire, mais encombre le code dans une certaine mesure. (Bien sûr, vous pouvez envelopper toutes ces choses dans une méthode.) À la fin, ce sera à vous de décider.
Éditer
Comme Doc Brown l'a souligné dans les commentaires, le problème n'est pas d'indiquer que la méthode lance, mais qu'elle ne lance pas. Dans NUnit, il y a aussi une affirmation pour que
la source
Ajoutez simplement un commentaire pour expliquer pourquoi aucune assertion n'est nécessaire et pourquoi vous ne l'avez pas oublié.
Comme vous pouvez le voir dans les autres réponses, toute autre chose rend le code plus compliqué et encombré. Avec le commentaire là-bas, d'autres programmeurs connaîtront l'intention du test.
Cela étant dit, ce type de test devrait être une exception (sans jeu de mots). Si vous vous retrouvez à écrire quelque chose comme ça régulièrement, alors les tests vous disent probablement que la conception n'est pas optimale.
la source
Vous pouvez également affirmer que certaines méthodes sont appelées (ou pas) correctement.
Par exemple:
Dans votre test:
la source