Comment écrire un unittest qui échoue uniquement si une fonction ne lève pas d'exception attendue?
python
unit-testing
exception
exception-handling
Daryl Spitzer
la source
la source
myfunc
vous devez les ajouter en tant qu'arguments à l'appel assertRaises. Voir la réponse de Daryl Spitzer.self.assertRaises(TypeError, mymod.myfunc)
. Vous pouvez trouver une liste complète des exceptions intégréesself.assertRaises(SomeCoolException, Constructor, arg1)
Depuis Python 2.7, vous pouvez utiliser le gestionnaire de contexte pour obtenir l'objet réel de l'exception levée:
http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises
En Python 3.5 , vous devez envelopper
context.exception
dansstr
, sinon vous aurez unTypeError
la source
context.exception
ne donne pas le message; c'est un type.import unittest2
, vous devez utiliserstr()
, c'est-à-direself.assertTrue('This is broken' in str(context.exception))
.Le code dans ma réponse précédente peut être simplifié pour:
Et si une fonction prend des arguments, passez-les simplement dans assertRaises comme ceci:
la source
2.7.15
. Siafunction
dansself.assertRaises(ExpectedException, afunction, arg1, arg2)
est l'initialiseur de classe, vous devez passerself
comme premier argument, par exemple,self.assertRaises(ExpectedException, Class, self, arg1, arg2)
Réponse courte:
Utilisez la
self.assertRaises
méthode comme gestionnaire de contexte:Manifestation
L'approche des meilleures pratiques est assez facile à démontrer dans un shell Python.
La
unittest
bibliothèqueEn Python 2.7 ou 3:
Dans Python 2.6, vous pouvez installer un backport de la
unittest
bibliothèque de 2.7 , appelé unittest2 , et juste alias cela commeunittest
:Exemples de tests
Maintenant, collez dans votre shell Python le test suivant de sécurité de type de Python:
Le test que l'on utilise
assertRaises
comme gestionnaire de contexte, ce qui garantit que l'erreur est correctement détectée et nettoyée pendant son enregistrement.Nous pourrions également l'écrire sans le gestionnaire de contexte, voir test deux. Le premier argument serait le type d'erreur que vous vous attendez à soulever, le deuxième argument, la fonction que vous testez, et les arguments et les arguments de mot-clé restants seront passés à cette fonction.
Je pense qu'il est beaucoup plus simple, lisible et maintenable de simplement utiliser le gestionnaire de contexte.
Exécution des tests
Pour exécuter les tests:
Dans Python 2.6, vous aurez probablement besoin des éléments suivants :
Et votre terminal devrait produire les informations suivantes:
Et nous voyons cela comme nous l'attendons, en essayant d'ajouter un
1
et un'1'
résultat dans unTypeError
.Pour une sortie plus détaillée, essayez ceci:
la source
Votre code doit suivre ce modèle (il s'agit d'un test de style de module le plus simple):
Sur Python <2.7, cette construction est utile pour vérifier des valeurs spécifiques dans l'exception attendue. La fonction unittest
assertRaises
vérifie uniquement si une exception a été déclenchée.la source
assertRaises
vous, vous obtiendrez une ERREUR au lieu d'un ÉCHEC.sur: http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/
Tout d'abord, voici la fonction correspondante (toujours dum: p) dans le fichier dum_function.py:
Voici le test à effectuer (seul ce test est inséré):
Nous sommes maintenant prêts à tester notre fonction! Voici ce qui se passe lorsque vous essayez d'exécuter le test:
L'erreur TypeError est déclenchée et génère un échec de test. Le problème est que c'est exactement le comportement que nous voulions: le par.
Pour éviter cette erreur, exécutez simplement la fonction à l'aide de lambda dans l'appel de test:
La sortie finale:
Parfait!
... et pour moi c'est parfait aussi !!
Merci beaucoup M. Julien Lengrand-Lambert
Cette affirmation de test renvoie en fait un faux positif . Cela se produit parce que le lambda à l'intérieur des 'assertRaises' est l'unité qui déclenche l'erreur de type et non la fonction testée.
la source
self.assertRaises(TypeError, df.square_value(self.false_int))
appelle la méthode et renvoie le résultat. Ce que vous voulez, c'est passer la méthode et tous les arguments et laisser les plus instants l'appeler:self.assertRaises(TypeError, df.square_value, self.false_int)
Vous pouvez créer le vôtre
contextmanager
pour vérifier si l'exception a été déclenchée.Et puis vous pouvez utiliser
raises
comme ceci:Si vous utilisez
pytest
, cette chose est déjà implémentée. Vous pouvez fairepytest.raises(Exception)
:Exemple:
Et le résultat:
la source
unittest
module!J'utilise doctest [1] presque partout parce que j'aime le fait que je documente et teste mes fonctions en même temps.
Jetez un œil à ce code:
Si vous placez cet exemple dans un module et l'exécutez à partir de la ligne de commande, les deux cas de test sont évalués et vérifiés.
[1] Documentation Python: 23.2 doctest - Test d'exemples interactifs Python
la source
Je viens de découvrir que la bibliothèque Mock fournit une méthode assertRaisesWithMessage () (dans sa sous-classe unittest.TestCase), qui vérifiera non seulement que l'exception attendue est déclenchée, mais également qu'elle est déclenchée avec le message attendu:
la source
Il y a beaucoup de réponses ici. Le code montre comment créer une exception, comment utiliser cette exception dans nos méthodes et, enfin, comment vérifier dans un test unitaire, les exceptions correctes étant levées.
la source
Vous pouvez utiliser assertRaises à partir du module unittest
la source
Comme je n'ai vu aucune explication détaillée sur la façon de vérifier si nous avons obtenu une exception spécifique parmi une liste acceptée à l'aide du gestionnaire de contexte, ou d'autres détails d'exception, j'ajouterai le mien (vérifié sur python 3.8).
Si je veux juste vérifier que la fonction augmente par exemple
TypeError
, j'écrirais:Si je veux vérifier que la fonction soulève l'un
TypeError
ou l' autreIndexError
, j'écrirais: avec self.assertRaises ((TypeError, IndexError)): function_raising_some_exception (parameters)Et si je veux encore plus de détails sur l'exception levée, je pourrais l'attraper dans un contexte comme celui-ci:
la source
Bien que toutes les réponses soient parfaitement correctes, je cherchais un moyen de tester si une fonction levait une exception sans s'appuyer sur des frameworks de tests unitaires et sans avoir à écrire des classes de test.
J'ai fini par écrire ce qui suit:
Et cela échoue sur la bonne ligne:
la source