Nehmen wir an, wir haben so etwas:
import py, pytest
ERROR1 = ' --- Error : value < 5! ---'
ERROR2 = ' --- Error : value > 10! ---'
class MyError(Exception):
def __init__(self, m):
self.m = m
def __str__(self):
return self.m
def foo(i):
if i < 5:
raise MyError(ERROR1)
elif i > 10:
raise MyError(ERROR2)
return i
# ---------------------- TESTS -------------------------
def test_foo1():
with pytest.raises(MyError) as e:
foo(3)
assert ERROR1 in str(e)
def test_foo2():
with pytest.raises(MyError) as e:
foo(11)
assert ERROR2 in str(e)
def test_foo3():
....
foo(7)
....
F: Wie kann ich test_foo3 () dazu bringen, zu testen, dass kein MyError ausgelöst wird? Es ist offensichtlich, dass ich nur testen konnte:
def test_foo3():
assert foo(7) == 7
aber ich möchte das über pytest.raises () testen. Ist das irgendwie möglich? Zum Beispiel: In einem Fall hat diese Funktion "foo" überhaupt keinen Rückgabewert.
def foo(i):
if i < 5:
raise MyError(ERROR1)
elif i > 10:
raise MyError(ERROR2)
Es könnte sinnvoll sein, diesen Weg zu testen, imho.
foo(7)
ist in Ordnung. Sie erhalten die richtige Nachricht und es ist einfacher, mit allen Pytest-Ausgaben zu debuggen. Der Vorschlag, den Sie von @Faruk ('Unexpected error...'
) erzwungen haben, sagt nichts über den Fehler aus und Sie werden stecken bleiben. Das einzige, was Sie tun können, um es besser zu machen, ist Ihre Absicht wie zu erklärentest_foo3_works_on_integers_within_range()
.Antworten:
Ein Test schlägt fehl, wenn eine unerwartete Ausnahme ausgelöst wird. Sie können einfach foo (7) aufrufen und haben getestet, dass kein MyError ausgelöst wird. Folgendes wird also ausreichen:
def test_foo3(): foo(7)
Wenn Sie explizit sein und eine Assert-Anweisung dafür schreiben möchten, können Sie Folgendes tun:
def test_foo3(): try: foo(7) except MyError: pytest.fail("Unexpected MyError ..")
quelle
Aufbauend auf dem, was Oisin erwähnt hat.
Sie können eine einfache
not_raises
Funktion erstellen, die ähnlich wie die von pytest funktioniertraises
:from contextlib import contextmanager @contextmanager def not_raises(exception): try: yield except exception: raise pytest.fail("DID RAISE {0}".format(exception))
Dies ist in Ordnung, wenn Sie sich an
raises
ein Gegenstück halten möchten und Ihre Tests daher besser lesbar sind. Im Wesentlichen benötigen Sie jedoch nichts anderes, als nur den Codeblock, den Sie testen möchten, in einer eigenen Zeile auszuführen - pytest schlägt ohnehin fehl, sobald dieser Block einen Fehler auslöst.quelle
@pytest.mark.parametrize
.Ich war gespannt, ob ein not_raises funktionieren würde. Ein schneller Test hierfür ist (test_notraises.py):
from contextlib import contextmanager @contextmanager def not_raises(ExpectedException): try: yield except ExpectedException, err: raise AssertionError( "Did raise exception {0} when it should not!".format( repr(ExpectedException) ) ) except Exception, err: raise AssertionError( "An unexpected exception {0} raised.".format(repr(err)) ) def good_func(): print "hello" def bad_func(): raise ValueError("BOOM!") def ugly_func(): raise IndexError("UNEXPECTED BOOM!") def test_ok(): with not_raises(ValueError): good_func() def test_bad(): with not_raises(ValueError): bad_func() def test_ugly(): with not_raises(ValueError): ugly_func()
Es scheint zu funktionieren. Ich bin mir jedoch nicht sicher, ob es im Test wirklich gut liest.
quelle