par*_*let 50 python raise pytest
让我们假设我们有这样的结果:
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)
....
Run Code Online (Sandbox Code Playgroud)
问:我如何让test_foo3()进行测试,没有引发MyError?很明显,我可以测试一下:
def test_foo3():
assert foo(7) == 7
Run Code Online (Sandbox Code Playgroud)
但我想通过pytest.raises()测试.有可能吗?例如:在一个案例中,该函数"foo"根本没有返回值,
def foo(i):
if i < 5:
raise MyError(ERROR1)
elif i > 10:
raise MyError(ERROR2)
Run Code Online (Sandbox Code Playgroud)
imho,用这种方式测试是有意义的.
Far*_*hin 92
如果测试引发任何意外的异常,测试将失败.你可以调用foo(7),你将测试不会引发MyError.所以,以下就足够了:
def test_foo3():
foo(7)
Run Code Online (Sandbox Code Playgroud)
如果你想明确并为此编写一个断言语句,你可以这样做:
def test_foo3():
try:
foo(7)
except MyError:
pytest.fail("Unexpected MyError ..")
Run Code Online (Sandbox Code Playgroud)
Pit*_*kos 12
建立在Oisin提到的基础之上..
你可以创建一个not_raises类似于pytest的简单函数raises:
from contextlib import contextmanager
@contextmanager
def not_raises(exception):
try:
yield
except exception:
raise pytest.fail("DID RAISE {0}".format(exception))
Run Code Online (Sandbox Code Playgroud)
如果你想坚持raises拥有一个对应物,那么你的测试更具可读性,这很好.从本质上讲,除了运行你想要在自己的行上测试的代码块之外,你真的不需要任何东西 - 一旦该块引发错误,pytest就会失败.
Nik*_*ikT 12
由于这个问题得到了回答,pytest 文档已经更新了关于这个主题的信息,这里值得一提。
https://docs.pytest.org/en/6.2.x/example/parametrize.html#parametrizing-conditional-rising
它与其他一些答案类似,但使用parametrize较新的内置函数nullcontext使解决方案非常干净。
一个潜在的Python3.7 +只例子如下所示:
from contextlib import nullcontext as does_not_raise
import pytest
@pytest.mark.parametrize(
"example_input,expectation",
[
(3, does_not_raise()),
(2, does_not_raise()),
(1, does_not_raise()),
(0, pytest.raises(ZeroDivisionError)),
],
)
def test_division(example_input, expectation):
"""Test how much I know division."""
with expectation:
assert (6 / example_input) is not None
Run Code Online (Sandbox Code Playgroud)
使用parametrize这种方式可以组合 OP 的测试用例,例如:
@pytest.mark.parametrize(
"example_input,expectation,message",
[
(3, pytest.raises(MyError), ERROR1),
(11, pytest.raises(MyError), ERROR2),
(7, does_not_raise(), None),
],
)
def test_foo(example_input, expectation, message):
with expectation as e:
foo(example_input)
assert message is None or message in str(e)
Run Code Online (Sandbox Code Playgroud)
这样做可以让您测试它没有引发任何异常。nullcontext是作为可选上下文管理器的替代品(pytest.raises在本例中为 )。它实际上没有做任何事情,所以如果你想测试它没有引发特定的异常,你应该看到其他答案之一。
我很想知道not_raises是否有效.对此的快速测试是(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()
Run Code Online (Sandbox Code Playgroud)
它确实有效.但是我不确定它是否真的在测试中读得很好.
| 归档时间: |
|
| 查看次数: |
31878 次 |
| 最近记录: |