Comment écrire un unittest qui échoue seulement si une fonction ne lève pas une exception attendue ?
Y a-t-il un moyen de faire l'inverse ? Par exemple, il n'y a d'échec que si la fonction lève l'exception ?
Comment écrire un unittest qui échoue seulement si une fonction ne lève pas une exception attendue ?
Utilice TestCase.assertRaises
(o TestCase.failUnlessRaises
) du module unittest, par exemple :
import mymod
class MyTestCase(unittest.TestCase):
def test1(self):
self.assertRaises(SomeCoolException, mymod.myfunc)
Y a-t-il un moyen de faire l'inverse ? Par exemple, il n'y a d'échec que si la fonction lève l'exception ?
Notez que pour passer des arguments à myfunc
vous devez les ajouter comme arguments à l'appel assertRaises. Voir la réponse de Daryl Spitzer.
Depuis Python 2.7, vous pouvez utiliser le gestionnaire de contexte pour obtenir l'objet d'exception lancé :
import unittest
def broken_function():
raise Exception('This is broken')
class MyTestCase(unittest.TestCase):
def test(self):
with self.assertRaises(Exception) as context:
broken_function()
self.assertTrue('This is broken' in context.exception)
if __name__ == '__main__':
unittest.main()
http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises
En Python 3.5 vous devez emballer context.exception
en str
sinon vous obtiendrez un TypeError
self.assertTrue('This is broken' in str(context.exception))
J'utilise Python 2.7.10, et ce qui précède ne fonctionne pas ; context.exception
ne donne pas le message ; c'est un type.
De même, dans Python 2.7 (du moins dans ma 2.7.6), l'utilisation de import unittest2
vous devez utiliser str()
c'est-à-dire self.assertTrue('This is broken' in str(context.exception))
.
Deux choses : 1. Vous pouvez utiliser assertIn au lieu de assertTrue. Par exemple, self.assertIn('This is broken', context.exception) 2. dans mon cas, avec la version 2.7.10, context.exception semble être un tableau de caractères. L'utilisation de str ne fonctionne pas. J'ai fini par faire ceci ''.join(context.exception) Donc, mis ensemble : self.assertIn('Ceci est cassé', ''.join(context.exception))
Le code de ma réponse précédente peut être simplifié comme suit :
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction)
Et si une fonction prend des arguments, il suffit de les passer dans assertRaises comme ceci :
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction, arg1, arg2)
Le deuxième extrait sur ce qu'il faut faire lorsque l'argument est passé était vraiment utile.
J'utilise 2.7.15
. Si afunction
en self.assertRaises(ExpectedException, afunction, arg1, arg2)
est l'initialisateur de la classe, vous devez passer le paramètre self
comme premier argument, par exemple, self.assertRaises(ExpectedException, Class, self, arg1, arg2)
Votre code devrait suivre ce modèle (c'est un test de style module unittest) :
def test_afunction_throws_exception(self):
try:
afunction()
except ExpectedException:
pass
except Exception:
self.fail('unexpected exception raised')
else:
self.fail('ExpectedException not raised')
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é levée.
Cela semble trop compliqué pour tester si une fonction lève une exception. Puisque toute exception autre que celle-là entraînera l'erreur du test et que le fait de ne pas lancer d'exception fera échouer le test, il semble que la seule différence soit que si vous obtenez une exception différente avec assertRaises
vous obtiendrez un ERREUR au lieu d'un ÉCHEC.
J'utilise doctest [1] presque partout car j'aime le fait de documenter et de tester mes fonctions en même temps.
Jetez un coup d'œil à ce code :
def throw_up(something, gowrong=False):
"""
>>> throw_up('Fish n Chips')
Traceback (most recent call last):
...
Exception: Fish n Chips
>>> throw_up('Fish n Chips', gowrong=True)
'I feel fine!'
"""
if gowrong:
return "I feel fine!"
raise Exception(something)
if __name__ == '__main__':
import doctest
doctest.testmod()
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 -- Tester les exemples interactifs Python
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.