Предположим, у нас есть что-то вроде этого:
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.raises (). Возможно ли как-нибудь? Например: в случае, когда функция "foo" вообще не имеет возвращаемого значения,
def foo(i):
if i < 5:
raise MyError(ERROR1)
elif i > 10:
raise MyError(ERROR2)
имеет смысл протестировать таким образом, imho.
foo(7)
все в порядке. Вы получите правильное сообщение, и вам будет легче отлаживать весь вывод pytest. Предложение, которое вы выдвинули из @Faruk ('Unexpected error...'
), ничего не говорит об ошибке, и вы застрянете. Единственное, что вы можете сделать, чтобы улучшить его, - это заявить о своем намеренииtest_foo3_works_on_integers_within_range()
.Ответы:
Тест завершится неудачно, если возникнет непредвиденное исключение. Вы можете просто вызвать foo (7), и вы убедитесь, что MyError не возникает. Итак, достаточно будет следующего:
def test_foo3(): foo(7)
Если вы хотите быть явным и написать для этого утверждение assert, вы можете сделать:
def test_foo3(): try: foo(7) except MyError: pytest.fail("Unexpected MyError ..")
источник
Основываясь на том, что упомянул Ойсин.
Вы можете создать простую
not_raises
функцию, которая действует аналогично pytestraises
:from contextlib import contextmanager @contextmanager def not_raises(exception): try: yield except exception: raise pytest.fail("DID RAISE {0}".format(exception))
Это нормально, если вы хотите, чтобы у вас
raises
был аналог и, таким образом, ваши тесты были более удобочитаемыми. По сути, однако, вам действительно не нужно ничего, кроме запуска блока кода, который вы хотите протестировать, в отдельной строке - pytest все равно завершится неудачно, как только этот блок вызовет ошибку.источник
@pytest.mark.parametrize
.Мне было любопытно посмотреть, сработает ли 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()
Кажется, это работает. Однако я не уверен, действительно ли он хорошо читается в тесте.
источник