bestsource

파이테스트를 사용하여 오류가 발생하지 않았는지 확인하는 방법

bestsource 2023. 6. 13. 22:27
반응형

파이테스트를 사용하여 오류가 발생하지 않았는지 확인하는 방법

우리가 그런 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

하지만 저는 그것을 파이테스트로 테스트하고 싶습니다. ㅠㅠ어떻게든 가능합니까?예를 들어, 어떤 경우, 함수 "foo"는 반환값이 전혀 없습니다.

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

이런 식으로 테스트하는 것이 말이 될 수 있습니다, 임호.

예기치 않은 예외가 발생하면 테스트가 실패합니다.foo(7)만 호출하면 MyError가 발생하지 않는지 테스트할 수 있습니다.따라서 다음과 같이 하면 충분합니다.

def test_foo3():
    foo(7)

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

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

이 질문에 대답한 이후로, 파이테스트 문서는 여기서 언급할 가치가 있는 이 주제에 대한 정보를 업데이트했습니다.

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

일부 다른 답변과 비슷하지만 다음을 사용합니다.parametrize그리고 새로운 기본 제공 기능nullcontext그것은 용액을 정말 깨끗하게 만듭니다.

잠재적인 Python 3.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

사용.parametrize이러한 방식을 통해 다음과 같은 OP의 테스트 사례를 결합할 수 있습니다.

@pytest.mark.parametrize(
    "example_input,expectation,message",
    [
        (3, pytest.raises(MyError), ERROR1),
        (11, pytest.raises(MyError), ERROR2),
        (7, does_not_raise(), None),
    ],
)
def test_foo(example_input, expectation, message):
    with expectation as e:
        foo(example_input)
    assert message is None or message in str(e)

이러한 방식으로 작업을 수행하면 예외발생하지 않았는지 테스트할 수 있습니다.nullcontext 는 선택적 컨텍스트 관리자(pytest.raises이 경우).실제로 아무것도 하지 않기 때문에 특정 예외를 제기하지 않았는지 테스트하려면 다른 답 중 하나를 확인해야 합니다.

오이신이 언급한 것 위에 건물을 짓는 것.

간단하게 만들 수 있습니다.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상대편이 있기 때문에 테스트를 더 쉽게 읽을 수 있습니다.그러나 본질적으로 테스트할 코드 블록을 자체 라인에서 실행하는 것 외에는 아무 것도 필요하지 않습니다. 어쨌든 해당 블록이 오류를 발생시키는 즉시 파이테스트가 실패합니다.

저는 안 올리는 게 효과가 있을지 궁금했습니다.이에 대한 간단한 테스트는 (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()

효과가 있는 것 같습니다.하지만 시험에서 그것이 정말 잘 읽히는지는 잘 모르겠습니다.

언급URL : https://stackoverflow.com/questions/20274987/how-to-use-pytest-to-check-that-error-is-not-raised

반응형