Pytest에서 경고 메시지 처리하기

경고 메시지 처리 방법

pytest 버전 3.1부터 테스트 실행 중 발생하는 모든 경고를 자동으로 캡처하고 세션 종료 시 보여줍니다. 아래는 기본적인 경고 캡처 예제입니다:

# test_show_warnings.py
import warnings

def api_v1():
    warnings.warn("api v1은 더 이상 사용되지 않으며, v2 함수를 사용하세요.", UserWarning)
    return 1

def test_one():
    assert api_v1() == 1
위 테스트를 실행하면 아래와 같은 출력을 볼 수 있습니다:

$ pytest test_show_warnings.py
=========================== test session starts ============================
platform linux -- Python 3.x.y,pytest-4.x.y,py-1.x.y,pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 1 item

test_show_warnings.py .                                             [100%]

============================= warnings summary =============================
test_show_warnings.py::test_one
  $REGENDOC_TMPDIR/test_show_warnings.py:5: UserWarning: api v1은 더 이상 사용되지 않으며, v2 함수를 사용하세요.
    warnings.warn("api v1은 더 이상 사용되지 않으며, v2 함수를 사용하세요.", UserWarning)

-- Docs: https://docs.pytest.org/en/latest/warnings.html
=================== 1 passed,1 warnings in 0.12 seconds ===================
### -W 옵션 사용하기 -W 플래그를 통해 표시할 경고 유형을 제어하거나 이를 오류로 변환할 수 있습니다. 예를 들어, 특정 경고를 강제로 에러로 만들려면 다음과 같이 설정합니다:

$ pytest -q test_show_warnings.py -W error::UserWarning
F                                                                    [100%]
================================= FAILURES =================================
_________________________________ test_one _________________________________

 def test_one():
>       assert api_v1() == 1

test_show_warnings.py:10:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

 def api_v1():
>       warnings.warn("api v1은 더 이상 사용되지 않으며, v2 함수를 사용하세요.", UserWarning)
E       UserWarning: api v1은 더 이상 사용되지 않으며, v2 함수를 사용하세요.

test_show_warnings.py:5: UserWarning
1 failed in 0.12 seconds
### @pytest.mark.filterwarnings 사용하기 특정 테스트 항목에 경고 필터를 적용할 수 있습니다:

import warnings

def api_v1():
    warnings.warn("api v1은 더 이상 사용되지 않으며, v2 함수를 사용하세요.", UserWarning)
    return 1

@pytest.mark.filterwarnings("ignore:api v1")
def test_one():
    assert api_v1() == 1
테스트 클래스나 모듈 전체에도 적용할 수 있습니다:

# 모듈 내 모든 경고를 에러로 처리
pytestmark = pytest.mark.filterwarnings("error")
### 경고 요약 비활성화 --disable-warnings 플래그를 사용하여 경고 요약을 완전히 비활성화할 수 있습니다. ### 특정 경고 확인하기 코드가 특정 경고를 트리거하는지 확인할 수 있습니다:

import pytest

def test_global():
    pytest.deprecated_call(myfunction, 17)
또는 컨텍스트 관리자로도 사용 가능합니다:

def test_global():
    with pytest.deprecated_call():
        myobject.deprecated_method()
### 특정 경고 발생 검증 특정 경고가 발생했는지 확인하려면 pytest.warns를 사용합니다:

import warnings
import pytest

def test_warning():
    with pytest.warns(UserWarning):
        warnings.warn("내 경고", UserWarning)
경고 메시지를 정규식으로 매칭할 수도 있습니다:

with pytest.warns(UserWarning, match='값은 반드시 0 또는 None이어야 합니다'):
    warnings.warn("값은 반드시 0 또는 None이어야 합니다.", UserWarning)
### 경고 기록하기 발생한 모든 경고를 기록하려면 recwarn 픽스처를 사용합니다:

import warnings

def test_hello(recwarn):
    warnings.warn("안녕하세요", UserWarning)
    assert len(recwarn) == 1
    w = recwarn.pop(UserWarning)
    assert issubclass(w.category, UserWarning)
    assert str(w.message) == "안녕하세요"
    assert w.filename
    assert w.lineno
### pytest 자체 경고 pytest도 자체적으로 몇 가지 경고를 생성할 수 있습니다. 예를 들어, 테스트 클래스가 __init__ 메서드를 정의한 경우 아래와 같은 경고가 나타납니다:

# test_pytest_warnings.py
class Test:
    def __init__(self):
        pass

    def test_foo(self):
        assert 1 == 1
실행 결과:

$ pytest test_pytest_warnings.py -q

============================= warnings summary =============================
test_pytest_warnings.py:1
  $REGENDOC_TMPDIR/test_pytest_warnings.py:1: PytestWarning: cannot collect test class 'Test' because it has a __init__ constructor
    class Test:

태그: Pytest warnings testing

7월 22일 10:27에 게시됨