[python] 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 : MyError가 발생하지 않는지 테스트하기 위해 test_foo3 ()을 어떻게 만들 수 있습니까? 내가 테스트 할 수 있다는 것은 분명합니다.

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)을 호출하면 MyError가 발생하지 않는지 테스트 할 수 있습니다. 따라서 다음으로 충분합니다.

def test_foo3():
    foo(7)

명시적이고 이에 대한 assert 문을 작성하려면 다음을 수행 할 수 있습니다.

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


답변

Oisin이 언급 한 것 위에 구축 ..

not_raisespytest와 유사 하게 작동 하는 간단한 함수를 만들 수 있습니다 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()

작동하는 것 같습니다. 그러나 나는 그것이 실제로 테스트에서 잘 읽는지 확실하지 않습니다.


답변