python - Cómo usar pytest para comprobar que el error NO se produce
py.test raise (3)
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 genere MyError? Es obvio, que podría simplemente 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, imho.
Sobre la base de lo que Oisin mencionó ...
Puedes hacer una función simple de not_raises
que actúe de manera similar a las subidas de pytest:
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 mantener las raises
teniendo una contraparte y, por lo tanto, sus pruebas sean más legibles. En esencia, sin embargo, no necesita nada más que simplemente 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.
Tenía curiosidad por ver si una 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 que funciona. Sin embargo, no estoy seguro de si realmente se lee bien en la prueba.
Una prueba fallará si genera cualquier tipo de excepción inesperada. Simplemente puede invocar foo (7) y habrá probado que no se ha generado MyError. Por lo tanto, bastará con lo siguiente:
def test_foo3():
foo(7)
Si desea ser explícito y escribir una declaración de afirmación para esto, puede hacer:
def test_foo3():
try:
foo(7)
except MyError:
pytest.fail("Unexpected MyError ..")