如何使用pytest检查是否未引发Error

时间:2013-11-28 21:29:54

标签: python pytest raise

让我们假设我们有这样的感觉:

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)
         ....

问:我如何让test_foo3()进行测试,没有引发MyError? 很明显,我可以测试一下:

def test_foo3():
    assert foo(7) == 7

但我想通过pytest.raises()进行测试。有可能吗? 例如:在某种情况下,该函数“foo”根本没有返回值,

def foo(i):
    if i < 5:
        raise MyError(ERROR1)
    elif i > 10:
        raise MyError(ERROR2)

以这种方式测试是有意义的,imho。

4 个答案:

答案 0 :(得分:73)

如果测试引发任何意外的异常,测试将失败。你可以调用foo(7),你将测试不会引发MyError。所以,以下就足够了:

def test_foo3():
    foo(7)

如果你想明确并为此写一个断言语句,你可以这样做:

def test_foo3():
    try:
        foo(7)
    except MyError:
        pytest.fail("Unexpected MyError ..")

答案 1 :(得分:10)

建立在Oisin所提到的基础之上..

您可以创建一个与pytest not_raises类似的简单raises函数:

from contextlib import contextmanager

@contextmanager
def not_raises(exception):
  try:
    yield
  except exception:
    raise pytest.fail("DID RAISE {0}".format(exception))

如果你想坚持让raises拥有对应物,那么你的测试更具可读性。从本质上讲,除了运行你想要在自己的行上测试的代码块之外,你真的不需要任何东西 - 一旦该块引发错误,pytest就会失败。

答案 2 :(得分:8)

自从这个问题得到回答后,pytest 文档已经更新了关于这个主题的信息,这里值得一提。

https://docs.pytest.org/en/6.2.x/example/parametrize.html#parametrizing-conditional-raising

它与其他一些答案类似,但使用 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

答案 3 :(得分:6)

我很想知道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()

它确实有效。但是我不确定它是否真的很好读 测试