Python assert Ausnahme

Neema Muganga 10 Oktober 2023
  1. Verwenden des Kontext-Managers zum Abfangen von Python assert Ausnahmen
  2. Verwenden von Schlüsselwortargumenten zum Abfangen von Python-Assert-Ausnahmen
Python assert Ausnahme

Dieser Artikel bringt einem zum Verständnis von assert als Testeinheit, um zu testen, ob die Funktionen Ausnahmen (Fehler, die während der Codeausführung erkannt werden) auslösen können, ohne die Ausführung unbedingt zu beenden. Mit anderen Worten, die ausgelöste Ausnahme ist gekapselt.

Dieser Test wird bestanden, wenn eine Ausnahme ausgelöst wird. Ein Fehler wird ausgelöst, wenn eine andere Ausnahme als die erwartete ausgelöst wird. In einem Fall, in dem überhaupt keine Ausnahme ausgelöst wird, schlägt der Test fehl.

Verwenden des Kontext-Managers zum Abfangen von Python assert Ausnahmen

Ähnlich wie es im allgemeinen Python-Konzept die Zuweisung und Freigabe von Ressourcen ermöglicht, wenn sie unbedingt erforderlich sind, erfasst der Kontext hier das tatsächliche Ausnahmeobjekt, das während des Tests ausgelöst wird.

Es speichert dieses Ausnahmeattribut im Objekt, wenn eine zusätzliche Leistungsprüfung der ausgelösten Ausnahme erforderlich ist.

Um zu testen, ob eine Funktion fehlschlägt oder besteht, ob eine Ausnahme ausgelöst wird oder nicht, verwenden wir TestCase.assertRaises aus dem Modul unittest.

Sehen wir uns ein praktisches Beispiel mit dem Kontextmanager an.

import unittest


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


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

Ausgabe:

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

OK

Im Beispielcode ist der Test erfolgreich, da wir erwarten, dass eine Ausnahme ausgelöst wird. Wir teilen 5 durch eine undefinierte Variable someNumber. Daher löst die Funktion eine NameError-Ausnahme aus. Daher besteht unser Test, wie durch das . in der ersten Zeile der Ausgabe angezeigt wird.

Sehen wir uns ein Beispiel an, bei dem der Test fehlschlägt, wenn keine Ausnahme ausgelöst wird.

import unittest


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


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

Ausgabe:

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)

In diesem Beispielcode definieren wir einen Wert für someNumber und führen dann den arithmetischen Ausdruck damit aus.

Die Ausgabe zeigt uns, dass der Test wie erwartet fehlschlägt. Wir erwarten diesmal keine NameError-Ausnahme, da ein definierter Wert für someNumber existiert.

Wir können den Kontextmanager auch mit benutzerdefinierten Ausnahmen wie im folgenden Beispiel implementieren.

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()

Ausgabe:

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

OK

Denken Sie daran, str zu verwenden, um die context.exception einzuschließen, um einen TypeError zu vermeiden.

Wir stellen assertTrue vor, eine unittest-Bibliothek, die beim Unit-Test einen Testwert mit true vergleicht.

Anstelle von assertTrue können Sie auch assertIn verwenden.

Beispiel:

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()

Wir sehen die gleiche Ausgabe, bei der die Testdurchläufe erzeugt werden.

Verwenden von Schlüsselwortargumenten zum Abfangen von Python-Assert-Ausnahmen

Anders als beim Kontextmanager, wo wir nur die Ausnahme an assertRaises() übergeben, übergeben wir auch den Funktionsaufruf und die Parameter der Funktion als Schlüsselwortargumente, um die Ausnahme hervorzurufen.

Syntax

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

Beispiel:

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()

Ausgabe:

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

OK

Der obige Beispielcode verwendet assertRaises() mit Schlüsselwortargumenten. Wir haben ihm die Ausnahme ZeroDivisionError übergeben, die erwartet wurde, nachdem versucht wurde, eine Zahl durch Null zu teilen. Als zweites Argument haben wir die Operatorfunktion importiert, die mit der Operatorfunktion floordiv verwendet wird. Parameterwerte sind hier die dritten Parameter; 55 durch 0 teilen.

Die letzte Anwendung von assert ist, wenn wir eine andere Ausnahme als die erwartete an assertRaises() übergeben. Stattdessen wird ein Fehler erzeugt.

Verwenden wir denselben Beispielcode, den wir gerade oben verwendet haben, und implementieren wir dies.

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()

Ausgabe:

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)

Aus der Ausgabe wird ein Fehler-Traceback erzeugt. Wir erwarten eine ZeroDivisionError-Ausnahme, wenn wir eine Zahl durch Null teilen. Stattdessen übergeben wir eine TypeError-Ausnahme, die angewendet wird, wenn eine arithmetische Operation zwischen verschiedenen Datentypen ausgeführt wird, beispielsweise einer Zeichenkette und einer Ganzzahl.

Verwandter Artikel - Python Exception