Supongamos que tenemos algo así:
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)
....
P: ¿Cómo puedo hacer test_foo3 () para probar que no se genera MyError? Es obvio que podría probar:
def test_foo3():
assert foo(7) == 7
pero quiero probar eso a través de pytest.raises (). ¿Es posible de alguna manera? Por ejemplo: en un caso, esa función "foo" no tiene ningún valor de retorno,
def foo(i):
if i < 5:
raise MyError(ERROR1)
elif i > 10:
raise MyError(ERROR2)
podría tener sentido probar de esta manera, en mi humilde opinión.
foo(7)
está bien. Obtendrá el mensaje correcto y será más fácil de depurar con toda la salida de pytest. La sugerencia que forzó de @Faruk ('Unexpected error...'
) no dice nada sobre el error y quedará atascado. Lo único que puede hacer para mejorarlo es expresar su intencióntest_foo3_works_on_integers_within_range()
.Respuestas:
Una prueba fallará si genera algún tipo de excepción inesperada. Puede simplemente invocar foo (7) y habrá probado que no se genera MyError. Entonces, lo siguiente será suficiente:
def test_foo3(): foo(7)
Si desea ser explícito y escribir una declaración de aserción para esto, puede hacer:
def test_foo3(): try: foo(7) except MyError: pytest.fail("Unexpected MyError ..")
fuente
Sobre la base de lo que Oisin mencionó.
Puede hacer una
not_raises
función simple que actúe de manera similar a la de pytestraises
:from contextlib import contextmanager @contextmanager def not_raises(exception): try: yield except exception: raise pytest.fail("DID RAISE {0}".format(exception))
Esto está bien si desea
raises
tener una contraparte y, por lo tanto, sus pruebas sean más legibles. Sin embargo, en esencia, no necesita nada más que ejecutar el bloque de código que desea probar en su propia línea; pytest fallará de todos modos tan pronto como ese bloque genere un error.fuente
@pytest.mark.parametrize
.Tenía curiosidad por ver si un not_raises funcionaría. Una prueba rápida de esto es (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()
Parece funcionar. Sin embargo, no estoy seguro de si realmente se lee bien en la prueba.
fuente