programing

pytest에서 예외가 발생한다고 올바르게 주장하는 방법은 무엇입니까?

luckcodes 2023. 1. 21. 10:24

pytest에서 예외가 발생한다고 올바르게 주장하는 방법은 무엇입니까?

코드:

# coding=utf-8
import pytest


def whatever():
    return 9/0

def test_whatever():
    try:
        whatever()
    except ZeroDivisionError as exc:
        pytest.fail(exc, pytrace=True)

출력:

================================ test session starts =================================
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
plugins: django, cov
collected 1 items 

pytest_test.py F

====================================== FAILURES ======================================
___________________________________ test_whatever ____________________________________

    def test_whatever():
        try:
            whatever()
        except ZeroDivisionError as exc:
>           pytest.fail(exc, pytrace=True)
E           Failed: integer division or modulo by zero

pytest_test.py:12: Failed
============================== 1 failed in 1.16 seconds ==============================

pytest print traceback을 만드는 방법.그래서 pytest print traceback의 위치를 확인할 수 있습니다.whatever함수에 예외가 발생했습니까?

pytest.raises(Exception) 그게 네게 필요한 거야

코드

import pytest

def test_passes():
    with pytest.raises(Exception) as e_info:
        x = 1 / 0

def test_passes_without_info():
    with pytest.raises(Exception):
        x = 1 / 0

def test_fails():
    with pytest.raises(Exception) as e_info:
        x = 1 / 1

def test_fails_without_info():
    with pytest.raises(Exception):
        x = 1 / 1

# Don't do this. Assertions are caught as exceptions.
def test_passes_but_should_not():
    try:
        x = 1 / 1
        assert False
    except Exception:
        assert True

# Even if the appropriate exception is caught, it is bad style,
# because the test result is less informative
# than it would be with pytest.raises(e)
# (it just says pass or fail.)

def test_passes_but_bad_style():
    try:
        x = 1 / 0
        assert False
    except ZeroDivisionError:
        assert True

def test_fails_but_bad_style():
    try:
        x = 1 / 1
        assert False
    except ZeroDivisionError:
        assert True

산출량

============================================================================================= test session starts ==============================================================================================
platform linux2 -- Python 2.7.6 -- py-1.4.26 -- pytest-2.6.4
collected 7 items 

test.py ..FF..F

=================================================================================================== FAILURES ===================================================================================================
__________________________________________________________________________________________________ test_fails __________________________________________________________________________________________________

    def test_fails():
        with pytest.raises(Exception) as e_info:
>           x = 1 / 1
E           Failed: DID NOT RAISE

test.py:13: Failed
___________________________________________________________________________________________ test_fails_without_info ____________________________________________________________________________________________

    def test_fails_without_info():
        with pytest.raises(Exception):
>           x = 1 / 1
E           Failed: DID NOT RAISE

test.py:17: Failed
___________________________________________________________________________________________ test_fails_but_bad_style ___________________________________________________________________________________________

    def test_fails_but_bad_style():
        try:
            x = 1 / 1
>           assert False
E           assert False

test.py:43: AssertionError
====================================================================================== 3 failed, 4 passed in 0.02 seconds ======================================================================================

주의:e_info는 예외 개체를 저장하므로 이 개체에서 세부 정보를 추출할 수 있습니다.예를 들어 예외 콜스택 또는 다른 네스트된 예외를 체크하는 경우입니다.

다음과 같은 것을 의미합니까?

def test_raises():
    with pytest.raises(Exception) as exc_info:   
        raise Exception('some info')
    # these asserts are identical; you can use either one   
    assert exc_info.value.args[0] == 'some info'
    assert str(exc_info.value) == 'some info'

pytest는 지속적으로 진화하며 최근의 좋은 변화 중 하나로 현재 동시에 테스트 가능

  • 예외 유형(예외 테스트)
  • 에러 메시지(정규 표현을 사용한 체크 또는 느슨한 체크)

이 매뉴얼에서는 다음 두 가지 예를 제시하겠습니다.

with pytest.raises(ValueError, match='must be 0 or None'):
    raise ValueError('value must be 0 or None')
with pytest.raises(ValueError, match=r'must be \d+$'):
    raise ValueError('value must be 42')

저는 그 방법을 여러 프로젝트에서 사용해 왔고 매우 좋아합니다.

주의: ilya-rusin의 이 코멘트는 앞서 말한 접근법도 시사한다.

pytest에서 이러한 종류의 사례를 처리하는 방법은 두 가지가 있습니다.

  • 사용.pytest.raises기능.

  • 사용.pytest.mark.xfail데코레이터

설명서에 기재되어 있는 바와 같이:

사용.pytest.raises자신의 코드가 의도적으로 발생하는 예외를 테스트하는 경우에는 더 나을 수 있습니다.@pytest.mark.xfail체크 기능이 있는 경우는, 수정되지 않은 버그를 문서화하는 것(테스트에 의해서 「필요」가 설명되는 것)이나 의존 관계에 있는 버그를 문서화하는 것이 좋을지도 모릅니다.

사용방법pytest.raises:

def whatever():
    return 9/0
def test_whatever():
    with pytest.raises(ZeroDivisionError):
        whatever()

사용방법pytest.mark.xfail:

@pytest.mark.xfail(raises=ZeroDivisionError)
def test_whatever():
    whatever()

출력pytest.raises:

============================= test session starts ============================
platform linux2 -- Python 2.7.10, pytest-3.2.3, py-1.4.34, pluggy-0.4.0 -- 
/usr/local/python_2.7_10/bin/python
cachedir: .cache
rootdir: /home/user, inifile:
collected 1 item

test_fun.py::test_whatever PASSED


======================== 1 passed in 0.01 seconds =============================

출력pytest.xfail마커:

============================= test session starts ============================
platform linux2 -- Python 2.7.10, pytest-3.2.3, py-1.4.34, pluggy-0.4.0 -- 
/usr/local/python_2.7_10/bin/python
cachedir: .cache
rootdir: /home/user, inifile:
collected 1 item

test_fun.py::test_whatever xfail

======================== 1 xfailed in 0.03 seconds=============================

해 볼 수 있습니다

def test_exception():
    with pytest.raises(Exception) as excinfo:   
        function_that_raises_exception()   
    assert str(excinfo.value) == 'some info' 

에서는 두 가지 방법으로 예외를 처리할 수 있습니다.pytest:

  1. 사용.pytest.raises제기된 예외에 대한 주장을 쓰다
  2. 사용.@pytest.mark.xfail

1. 사용방법pytest.raises

문서에서:

발생한 예외에 대한 주장을 작성하려면 다음을 사용하여 작성할 수 있습니다.pytest.raises콘텍스트 매니저로서

예:

예외만을 주장하는 경우:

import pytest


def test_zero_division():
    with pytest.raises(ZeroDivisionError):
        1 / 0

with pytest.raises(ZeroDivisionError)다음 코드 블록에 무엇이 있든 간에ZeroDivisionError예외.예외가 발생하지 않으면 테스트는 실패합니다.테스트에서 다른 예외가 발생하면 실패합니다.

실제 예외 정보에 액세스할 필요가 있는 경우:

import pytest

def f():
    f()

def test_recursion_depth():
    with pytest.raises(RuntimeError) as excinfo:
        f()
    assert "maximum recursion" in str(excinfo.value)

excinfo는 입니다.ExceptionInfoinstance: 실제로 발생한 예외를 둘러싼 래퍼입니다.주요 관심 속성은 다음과 같습니다..type,.value그리고..traceback.

2. 사용방법@pytest.mark.xfail

또, 다음과 같이 지정할 수도 있습니다.raises에 대한 의론.pytest.mark.xfail.

import pytest

@pytest.mark.xfail(raises=IndexError)
def test_f():
    l = [1, 2, 3]
    l[10]

@pytest.mark.xfail(raises=IndexError)다음 코드 블록에 무엇이 있든지 간에IndexError. ㅇㅇㅇㅇ이면IndexError하면 '이 올라가다'로 표시됩니다.xfailed (x)하지 않을 는 "예외가 발생하지 않을 로 표시됩니다xpassed (X)테스트에서 다른 예외가 발생하면 실패합니다.

주의:

  • 「」를 사용합니다.pytest.raises에서는, 의 코드가 발생시키고 는, 「예외 」를 사용하는 것이 가능성이 .@pytest.mark.xfail수정되지 않은 버그나 의존관계에 있는 버그를 문서화하는 등에는 체크 기능이 있는 것이 좋습니다.

  • 할 수 요.matchcontext-manager ('pytest.raises): 정규 표현이 예외 문자열 표현과 일치하는지 테스트합니다.(자세한 것은 이쪽)

은 바바용 right를 사용하는 것입니다.pytest.raises하지만 나는 여기서 흥미로운 대체 방법을 발견했고, 이 질문을 나중에 독자들에게 남겨두고 싶다.

try:
    thing_that_rasises_typeerror()
    assert False
except TypeError:
    assert True

이 솔루션을 사용하고 있습니다.

def test_date_invalidformat():
    """
    Test if input incorrect data will raises ValueError exception
    """
    date = "06/21/2018 00:00:00"
    with pytest.raises(ValueError):
        app.func(date) #my function to be tested

https://docs.pytest.org/en/latest/reference.html#pytest-raises 의 pytest 를 참조해 주세요.

특정 오류 유형을 테스트하려면 try, catch 및 raise 조합을 사용합니다.

#-- test for TypeError
try:
  myList.append_number("a")
  assert False
except TypeError: pass
except: assert False

여기에 제시된 상위 답변은 테스트 케이스에 대해 예외가 발생할 것으로 예상되는 경우에 유용합니다.테스트에서 예외가 발생할 수 있고 어느 시나리오에서도 우아하게 대처하고 싶은 경우에는 그다지 유용하지 않습니다.

예외가 발생할 수 있는 테스트 케이스가 있다면 이것이 더 나은 선택이라고 생각합니다.

@python.mark.parametrize("request_query, response_code", query_response_dataset)
def test_big_query_submission(request_query, response_code):
    try:
        stats = bigquery.Client().query(request_query)
    except Exception as e:
        assert False, f"Exception raised: {e}"
    assert stats.errors is None

이렇게 하면 어떤 이유로든 발생한 예외로 인해 테스트를 중단하지 않고 정상적으로 불합격할 수 있습니다.

가장 좋은 방법은 끊임없이 계승되는 클래스를 사용하는 것입니다.TestCase 및 running self.assertRaises.

예를 들어 다음과 같습니다.

import unittest


def whatever():
    return 9/0


class TestWhatEver(unittest.TestCase):

    def test_whatever():
        with self.assertRaises(ZeroDivisionError):
            whatever()

그런 다음 다음을 실행하여 실행합니다.

pytest -vs test_path

난 그냥 모든 시험을 볼 때마다 갈고리를 썼을 뿐이야

훅:

@pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(항목:항목, 호출: CallInfo):

    outcome = yield  # The result after the test is completed
    result = outcome.get_result()

    if result.when == "call":
       if result.failed == True:

       else:

테스트 결과로 문서를 업데이트하고 : result.longrepr.reprcrash.message를 사용하여 트레이스를 추가하는 기능이 있습니다.

이것이 최선의 방법인지는 모르겠지만 pytest만을 사용하여 트레이스 백을 인쇄하는 방법에 대한 질문에 대한 답은 됩니다.

@분명히 나는 다른 코드를 가지고 있다.

"pytrace=True"를 제거해 보셨습니까?

pytest.fail(exc, pytrace=True) # before
pytest.fail(exc) # after

'--fulltrace'로 달려본 적 있나요?

언급URL : https://stackoverflow.com/questions/23337471/how-to-properly-assert-that-an-exception-gets-raised-in-pytest