Wie schreibt man eine Unittest, die nur fehlschlägt, wenn eine Funktion keine erwartete Ausnahme auslöst?
python
unit-testing
exception
exception-handling
Daryl Spitzer
quelle
quelle
myfunc
Sie zum Übergeben von Argumenten diese als Argumente zum assertRaises-Aufruf hinzufügen müssen. Siehe Daryl Spitzers Antwort.self.assertRaises(TypeError, mymod.myfunc)
. Eine vollständige Liste der integrierten Ausnahmen finden Sie hier: docs.python.org/3/library/exceptions.html#bltin-exceptionsself.assertRaises(SomeCoolException, Constructor, arg1)
Seit Python 2.7 können Sie den Kontextmanager verwenden, um das tatsächlich ausgelöste Exception-Objekt abzurufen:
http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises
In Python 3.5 , müssen Sie wickeln
context.exception
instr
, sonst werden Sie eine bekommenTypeError
quelle
context.exception
gibt die Nachricht nicht; Es ist ein Typ.import unittest2
müssen Sie verwendenstr()
, dhself.assertTrue('This is broken' in str(context.exception))
.Der Code in meiner vorherigen Antwort kann vereinfacht werden zu:
Und wenn eine Funktion Argumente benötigt, geben Sie sie einfach an assertRaises wie folgt weiter:
quelle
2.7.15
. Wennafunction
inself.assertRaises(ExpectedException, afunction, arg1, arg2)
der Klasseninitialisierer ist, müssen Sieself
als erstes Argument übergeben, z. B.self.assertRaises(ExpectedException, Class, self, arg1, arg2)
Kurze Antwort:
Verwenden Sie die
self.assertRaises
Methode als Kontextmanager:Demonstration
Der Best-Practice-Ansatz lässt sich in einer Python-Shell recht einfach demonstrieren.
Die
unittest
BibliothekIn Python 2.7 oder 3:
In Python 2.6 können Sie einen Backport der
unittest
Bibliothek von 2.7 mit dem Namen unittest2 installieren und den folgenden Alias verwendenunittest
:Beispieltests
Fügen Sie nun den folgenden Test der Typensicherheit von Python in Ihre Python-Shell ein:
Test One wird
assertRaises
als Kontextmanager verwendet, der sicherstellt, dass der Fehler während der Aufzeichnung ordnungsgemäß abgefangen und bereinigt wird.Wir könnten es auch ohne den Kontextmanager schreiben , siehe Test zwei. Das erste Argument ist der Fehlertyp, den Sie voraussichtlich auslösen werden, das zweite Argument, die zu testende Funktion und die verbleibenden Argumente und Schlüsselwortargumente werden an diese Funktion übergeben.
Ich denke, es ist viel einfacher, lesbarer und wartbarer, nur den Kontextmanager zu verwenden.
Ausführen der Tests
So führen Sie die Tests aus:
In Python 2.6 benötigen Sie wahrscheinlich Folgendes :
Und Ihr Terminal sollte Folgendes ausgeben:
Und wir sehen das wie erwartet, wenn wir versuchen, a
1
und ein'1'
Ergebnis in a hinzuzufügenTypeError
.Versuchen Sie Folgendes, um eine ausführlichere Ausgabe zu erhalten:
quelle
Ihr Code sollte diesem Muster folgen (dies ist ein ungeeigneter Test im Modulstil):
Unter Python <2.7 ist dieses Konstrukt nützlich, um in der erwarteten Ausnahme nach bestimmten Werten zu suchen. Die Funktion unittest
assertRaises
prüft nur, ob eine Ausnahme ausgelöst wurde.quelle
assertRaises
erhalten, einen FEHLER anstelle eines FEHLERS erhalten.von: http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/
Hier ist zunächst die entsprechende (noch dum: p) Funktion in der Datei dum_function.py:
Hier ist der durchzuführende Test (nur dieser Test wird eingefügt):
Wir sind jetzt bereit, unsere Funktion zu testen! Folgendes passiert, wenn versucht wird, den Test auszuführen:
Der TypeError wird aktiv ausgelöst und generiert einen Testfehler. Das Problem ist, dass dies genau das Verhalten ist, das wir wollten: s.
Um diesen Fehler zu vermeiden, führen Sie einfach die Funktion mit Lambda im Testaufruf aus:
Die endgültige Ausgabe:
Perfekt !
... und für mich ist es auch perfekt !!
Vielen Dank Herr Julien Lengrand-Lambert
Diese Testaussage gibt tatsächlich ein falsches Positiv zurück . Dies geschieht, weil das Lambda in 'assertRaises' die Einheit ist, die einen Typfehler auslöst, und nicht die getestete Funktion.
quelle
self.assertRaises(TypeError, df.square_value(self.false_int))
ruft die Methode auf und gibt das Ergebnis zurück. Was Sie wollen, ist, die Methode und alle Argumente zu übergeben und die Unittest es nennen zu lassen:self.assertRaises(TypeError, df.square_value, self.false_int)
Sie können Ihre eigenen erstellen
contextmanager
, um zu überprüfen, ob die Ausnahme ausgelöst wurde.Und dann können Sie so verwenden
raises
:Wenn Sie verwenden
pytest
, ist dieses Ding bereits implementiert. Sie können tunpytest.raises(Exception)
:Beispiel:
Und das Ergebnis:
quelle
unittest
Modul nicht erforderlich ist !Ich benutze doctest [1] fast überall, weil mir die Tatsache gefällt, dass ich meine Funktionen gleichzeitig dokumentiere und teste .
Schauen Sie sich diesen Code an:
Wenn Sie dieses Beispiel in ein Modul einfügen und über die Befehlszeile ausführen, werden beide Testfälle ausgewertet und überprüft.
[1] Python-Dokumentation: 23.2 doctest - Testen Sie interaktive Python-Beispiele
quelle
Ich habe gerade festgestellt, dass die Mock-Bibliothek eine assertRaisesWithMessage () -Methode (in ihrer unittest.TestCase-Unterklasse) bereitstellt, die nicht nur überprüft, ob die erwartete Ausnahme ausgelöst wird, sondern auch, ob sie mit der erwarteten Nachricht ausgelöst wird:
quelle
Hier gibt es viele Antworten. Der Code zeigt, wie wir eine Ausnahme erstellen können, wie wir diese Ausnahme in unseren Methoden verwenden können und wie Sie schließlich in einem Komponententest überprüfen können, ob die richtigen Ausnahmen ausgelöst werden.
quelle
Sie können assertRaises aus dem unittest-Modul verwenden
quelle
Obwohl alle Antworten vollkommen in Ordnung sind, suchte ich nach einer Möglichkeit zu testen, ob eine Funktion eine Ausnahme auslöst, ohne sich auf Unit-Test-Frameworks zu verlassen und Testklassen schreiben zu müssen.
Am Ende schrieb ich Folgendes:
Und es scheitert auf der richtigen Linie:
quelle