Python 如何使用 pytest 检查错误没有被引发

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20274987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:04:32  来源:igfitidea点击:

How to use pytest to check that Error is NOT raised

pythonpytestraise

提问by paraklet

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 :

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

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,

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

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

it could make sense to test this way, imho.

以这种方式进行测试是有意义的,恕我直言。

采纳答案by Faruk Sahin

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:

如果它引发任何类型的意外异常,测试将失败。您可以只调用 foo(7) 并且您将测试没有引发 MyError 。因此,以下内容就足够了:

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

回答by Oisin

I was curious to see if a not_raises would work. A quick test of this is (test_notraises.py):

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

It does seem to work. However I'm not sure if it really reads well in the test.

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

回答by Pithikos

Building on top of what Oisin mentioned..

建立在 Oisin 提到的基础之上。

You can make a simple not_raisesfunction that acts similar to pytest's raises:

您可以创建一个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))

This is fine if you want to stick to having raiseshaving 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.

如果您想坚持raises拥有一个副本,从而使您的测试更具可读性,这很好。然而,本质上,除了在自己的行上运行要测试的代码块之外,您实际上并不需要任何东西 - 一旦该块引发错误,pytest 无论如何都会失败。