Wie testet man, dass eine Python-Funktion eine Ausnahme auslöst?
Wie kann man einen Test schreiben, der nur dann fehlschlägt, wenn eine Funktion keine eine erwartete Ausnahme auslöst?
Kurze Antwort:
Verwenden Sie die self.assertRaises
Methode als Kontextmanager:
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
Demonstration
Der Best-Practice-Ansatz lässt sich recht einfach in einer Python-Shell demonstrieren.
El unittest
Bibliothek
In Python 2.7 oder 3:
import unittest
In Python 2.6 können Sie einen Backport der 2.7er Version installieren unittest
Bibliothek, genannt ungetestet2 und benennen Sie es einfach als unittest
:
import unittest2 as unittest
Beispieltests
Fügen Sie nun in Ihrer Python-Shell den folgenden Test der Typsicherheit von Python ein:
class MyTestCase(unittest.TestCase):
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
def test_2_cannot_add_int_and_str(self):
import operator
self.assertRaises(TypeError, operator.add, 1, '1')
Test eins verwendet assertRaises
als Kontextmanager, der sicherstellt, dass der Fehler ordnungsgemäß abgefangen und bereinigt wird, während er aufgezeichnet wird.
Wir könnten es auch so schreiben ohne den Kontextmanager, siehe Test zwei. Das erste Argument ist der Fehlertyp, den Sie erwarten, das zweite Argument ist die Funktion, die Sie testen, und die übrigen Args und Keyword-Args werden an diese Funktion übergeben.
Ich denke, es ist viel einfacher, lesbarer und wartbarer, einfach den Kontextmanager zu verwenden.
Durchführung der Tests
So führen Sie die Tests durch:
unittest.main(exit=False)
In Python 2.6 werden Sie wahrscheinlich benötigen Folgendes :
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))
Und Ihr Terminal sollte folgendes ausgeben:
..
----------------------------------------------------------------------
Ran 2 tests in 0.007s
OK
<unittest2.runner.TextTestResult run=2 errors=0 failures=0>
Und wir sehen, dass, wie erwartet, der Versuch, eine 1
y un '1'
führen zu einer TypeError
.
Wenn Sie eine ausführlichere Ausgabe wünschen, versuchen Sie dies:
unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))