Exception d'assertion Python

Neema Muganga 10 octobre 2023
  1. Utilisation du gestionnaire de contexte pour intercepter l’exception d’assertion Python
  2. Utilisation d’arguments de mot-clé pour attraper l’exception d’assertion Python
Exception d'assertion Python

Cet article amène à comprendre assert comme une unité de test, pour tester que les fonctions peuvent lever des exceptions (erreurs détectées lors de l’exécution du code) sans nécessairement sortir de l’exécution. En d’autres termes, l’exception levée est encapsulée.

Ce test réussira si une exception est levée. Une erreur est levée si une exception différente de celle attendue est levée. Dans un cas où il n’y a aucune exception levée, le test échoue.

Utilisation du gestionnaire de contexte pour intercepter l’exception d’assertion Python

Semblable à la façon dont il permet l’allocation et la libération de ressources lorsque cela est nécessairement requis dans le concept python général, le contexte saisit ici l’objet d’exception réel qui est lancé pendant le test.

Il stocke cet attribut d’exception dans l’objet s’il est nécessaire d’effectuer un contrôle de performance supplémentaire sur l’exception déclenchée.

Pour tester qu’une fonction échoue ou réussit, qu’une exception soit levée ou non, nous utiliserons TestCase.assertRaises du module unittest.

Voyons un exemple pratique utilisant le gestionnaire de contexte.

import unittest


class TestCase(unittest.TestCase):
    def test_nameerror(self):
        with self.assertRaises(Exception):
            100 * (someNumber / 5)


if __name__ == "__main__":
    unittest.main()

Production:

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

Dans l’exemple de code, le test réussit car nous nous attendons à ce qu’une exception soit levée. Nous divisons 5 par une variable indéfinie someNumber. Par conséquent, la fonction lève une exception NameError. Par conséquent, notre test réussit comme indiqué par le . dans la première ligne de la sortie.

Voyons un exemple où le test échoue lorsqu’une exception n’est pas levée.

import unittest


class TestCase(unittest.TestCase):
    def test_nameerror(self):
        with self.assertRaises(Exception):
            someNumber = 10
            100 * (someNumber / 5)


if __name__ == "__main__":
    unittest.main()

Production:

F
======================================================================
FAIL: test_nameerror (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):  File "c:\Users\Neema\Desktop\Article Requirement Spec and Example 
Articles\Article Requirement Spec 
and Example Articles\fah.py", line 106, in test_nameerror
    100 * (someNumber/5)
AssertionError: Exception not raised

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)

Dans cet exemple de code, nous définissons une valeur pour someNumber puis nous effectuons l’expression arithmétique avec.

La sortie nous montre que le test échoue comme prévu. Nous ne nous attendons pas à ce qu’une exception NameError soit levée cette fois car une valeur définie pour someNumber existe.

Nous pouvons également implémenter le gestionnaire de contexte en utilisant des exceptions définies par l’utilisateur comme dans l’exemple suivant.

import unittest


def user_function():
    raise Exception("A user-defined exception")


class MyTestCase(unittest.TestCase):
    def test_userexception(self):
        with self.assertRaises(Exception) as context:
            user_function()

        self.assertTrue("A user-defined exception" in str(context.exception))


if __name__ == "__main__":
    unittest.main()

Production:

.
----------------------------------------------------------------------
Ran 1 test in 0.006s

OK

N’oubliez pas d’utiliser str pour entourer le context.exception pour éviter d’obtenir une TypeError.

Nous introduisons assertTrue, une bibliothèque unittest qui compare une valeur de test avec true dans les tests unitaires.

Vous pouvez également choisir d’utiliser assertIn au lieu de assertTrue.

Exemple:

import unittest


def user_function():
    raise Exception("A use defined exception")


class MyTestCase(unittest.TestCase):
    def test_userexception(self):
        with self.assertRaises(Exception) as context:
            user_function()

        self.assertIn("A use defined exception", str(context.exception))


if __name__ == "__main__":
    unittest.main()

Nous voyons la même sortie où les tests réussis seront produits.

Utilisation d’arguments de mot-clé pour attraper l’exception d’assertion Python

Contrairement au gestionnaire de contexte, où l’on ne passe que l’exception à assertRaises(), on passe également l’appel de fonction et les paramètres de la fonction comme arguments mot-clé pour évoquer l’exception.

Syntaxe

assertRaises(exception, function, *args, **keywords)

Exemple:

import unittest


class MyTestCase(unittest.TestCase):
    def test_division_by_error(self):
        import operator

        self.assertRaises(ZeroDivisionError, operator.floordiv, 55, 0)


if __name__ == "__main__":
    unittest.main()

Production:

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

L’exemple de code ci-dessus utilisait assertRaises() avec des arguments de mot-clé. Nous lui avons passé l’exception ZeroDivisionError attendue après avoir tenté de diviser un nombre par zéro. Nous avons importé la fonction opérateur utilisée avec la fonction opérateur floordiv comme deuxième argument. Les valeurs des paramètres ici sont les troisièmes paramètres ; 55 pour diviser par 0.

La dernière application de assert est lorsque nous passons une exception différente de celle attendue à assertRaises(). Une erreur est générée à la place.

En utilisant le même exemple de code que nous venons d’utiliser ci-dessus, implémentons ceci.

import unittest


class MyTestCase(unittest.TestCase):
    def test_division_by_error(self):
        import operator

        self.assertRaises(TypeError, operator.floordiv, 55, 0)


if __name__ == "__main__":
    unittest.main()

Production:

E
======================================================================
ERROR: test_division_by_error (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):  File "c:\Users\Neema\Desktop\Article Requirement Spec and Example 
Articles\user.py", line 16, in test_division_by_error
    self.assertRaises(TypeError, operator.floordiv, 55, 0)
  File "C:\Users\Neema\AppData\Local\Programs\Python\Python39\lib\unittest\case.py", line 733, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "C:\Users\Neema\AppData\Local\Programs\Python\Python39\lib\unittest\case.py", line 201, in handle
    callable_obj(*args, **kwargs) 
ZeroDivisionError: integer division or modulo by zero

----------------------------------------------------------------------
Ran 1 test in 0.031s

FAILED (errors=1)

À partir de la sortie, une trace d’erreur est produite. Nous attendons une exception ZeroDivisionError lorsque nous divisons un nombre par zéro. Au lieu de cela, nous passons une exception TypeError appliquée lors de l’exécution d’une opération arithmétique entre différents types de données, disons une chaîne et un entier.

Article connexe - Python Exception