Как использовать pytest, чтобы проверить, что ошибка не возникает

предположим, что у нас есть smth так:

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: Как я могу сделать test_foo3 (), чтобы проверить, что MyError не поднимается? Очевидно, что я мог бы просто проверить :

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

но я хочу проверить это через pytest.поднимет.)( Возможно ли это каким-то образом? Например: в случае, если эта функция " foo " вообще не имеет возвращаемого значения,

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

это может иметь смысл проверить таким образом, имхо.

3 ответов


тест завершится неудачей, если он вызовет какое-либо непредвиденное исключение. Вы можете просто вызвать foo (7), и вы проверите, что MyError не вызывается. Итак, достаточно будет следующего:

def test_foo3():
    foo(7)

Если вы хотите быть явным и написать оператор assert для этого, вы можете сделать:

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

здание поверх того, что упомянул Ойсин..

вы можете сделать простой 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))

это нормально, если вы хотите придерживаться имеющего raises наличие аналога и, следовательно, ваши тесты более читабельны. По сути, вам действительно ничего не нужно, кроме запуска блока кода, который вы хотите протестировать на своей собственной строке - pytest все равно потерпит неудачу, как только этот блок вызовет ошибку.


мне было любопытно посмотреть, будет ли работать 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()

похоже, это работает. Однако я не уверен, действительно ли это хорошо читается в тест.