티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

How to use pytest to check that Error is NOT raised

pytest를 사용하여 오류가 발생하지 않았는지 확인하는 방법

 문제 내용 

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 :

Q: MyError가 발생하지 않도록 test_foo3()를 테스트하려면 어떻게 해야 합니까? 내가 그냥 테스트할 수 있다는 것은 명백하다.
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.

제 생각은 이런 식으로 테스트하는 것이 합리적일 수 있을 것 같습니다.

 

 

 

 높은 점수를 받은 Solution 

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:

명시적이고 이에 대한 assert 문을 작성하려면 다음을 수행할 수 있습니다.
def test_foo3():
    try:
        foo(7)
    except MyError:
        pytest.fail("Unexpected MyError ..")

 

 

 가장 최근 달린 Solution 

Since this question was answered, the pytest docs have updated info on this subject that's worth mentioning here.

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

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

 

Parametrizing tests — pytest documentation

Parametrizing tests pytest allows to easily parametrize test functions. For basic docs, see Parametrizing fixtures and test functions. In the following we provide some examples using the builtin mechanisms. Generating parameters combinations, depending on

docs.pytest.org

 

It's similar to some of the other answers, but using parametrize and a newer builtin nullcontext that makes the solution really clean.

다른 답변과 비슷하지만 솔루션을 정말 깨끗하게 만드는 parametrize 및 최신 내장 nullcontext를 사용합니다.

 

A potential Python3.7+ only example would look like:

잠재적인 파이썬 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

 

Using parametrize this way makes it possible to combine OP's test cases, like:

이 방법으로 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)

 

Doing it this way allows you to test that it did not raise any exception. nullcontext is meant as a stand in for an optional context manager (pytest.raises, in this case). It's not actually doing anything, so if you wanted to test that it did NOT raise a specific exception, you should see one of the other answers.

이렇게 하면 예외가 발생하지 않았는지 테스트할 수 있습니다. nullcontext는 선택적 컨텍스트 관리자(이 경우 pytest.raises)를 의미합니다. 실제로 아무 작업도 수행하지 않으므로 특정 예외가 발생하지 않았는지 테스트하려면 다른 답변 중 하나를 확인해야 합니다.

 

 

 

출처 : https://stackoverflow.com/questions/20274987/how-to-use-pytest-to-check-that-error-is-not-raised

반응형
댓글
공지사항
최근에 올라온 글