경고 메시지 처리 방법
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: