问题
Let's assume we have smth like that :
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)
....
Q: How can I make test_foo3() to test, that no MyError is raised? It's obvious, that i could just test :
def test_foo3():
assert foo(7) == 7
but i want to test that via pytest.raises(). Is is possible someway? For example: in a case, that function "foo" has no return-value at all,
def foo(i):
if i < 5:
raise MyError(ERROR1)
elif i > 10:
raise MyError(ERROR2)
it could make sense to test this way, imho.
回答1:
A test will fail if it raises any kind of unexpected Exception. You can just invoke foo(7) and you will have tested that no MyError is raised. So, following will suffice:
def test_foo3():
foo(7)
If you want to be explicit and write an assert statement for this, you can do:
def test_foo3():
try:
foo(7)
except MyError:
pytest.fail("Unexpected MyError ..")
回答2:
Building on top of what Oisin mentioned..
You can make a simple not_raises
function that acts similar to pytest's raises
:
from contextlib import contextmanager
@contextmanager
def not_raises(exception):
try:
yield
except exception:
raise pytest.fail("DID RAISE {0}".format(exception))
This is fine if you want to stick to having raises
having a counterpart and thus your tests being more readable. In essence however you don't really need anything than just running the block of code you want to test on its own line - pytest will fail anyway as soon as that block raises an error.
回答3:
I was curious to see if a not_raises would work. A quick test of this is (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()
It does seem to work. However I'm not sure if it really reads well in the test.
来源:https://stackoverflow.com/questions/20274987/how-to-use-pytest-to-check-that-error-is-not-raised