Pytest權威教程10-捕獲警告信息


返回: Pytest權威教程

捕獲警告信息

3.1版中的新函數。

從版本開始3.1,pytest現在會在測試執行期間自動捕獲警告並在會話結束時顯示它們:

# content of test_show_warnings.py
import warnings

def api_v1():
    warnings.warn(UserWarning("api v1,should use functions from v2"))
    return 1

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

運行pytest現在產生這個輸出:

$ 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,should use functions from v2
    warnings.warn(UserWarning("api v1,should use functions from v2"))

-- Docs: https://docs.pytest.org/en/latest/warnings.html
=================== 1 passed,1 warnings in 0.12 seconds ===================

-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(UserWarning("api v1,should use functions from v2"))
E       UserWarning: api v1,should use functions from v2

test_show_warnings.py:5: UserWarning
1 failed in 0.12 seconds

可以pytest.ini使用filterwarningsini選項在文件中設置相同的選項。例如,以下配置將忽略所有用戶警告,但會將所有其他警告轉換為錯誤。

[pytest]
filterwarnings =
 error
 ignore::UserWarning

當警告與列表中的多個選項匹配時,將執行最后一個匹配選項的操作。

這兩個-W命令行選項和filterwarningsINI選項是基於Python的[-W選項,所以請參考這些部分Python文檔的其他例子和高級的使用方法英寸

@pytest.mark.filterwarnings

版本3.2中的新函數。

你可以使用@pytest.mark.filterwarnings向特定測試項添加警告過濾器,以便更好地控制應在測試,類甚至模塊級別捕獲哪些警告:

import warnings

def api_v1():
    warnings.warn(UserWarning("api v1,should use functions from v2"))
    return 1

@pytest.mark.filterwarnings("ignore:api v1")
def test_one():
    assert api_v1() == 1

使用標記應用的過濾器優先於在命令行上傳遞或由filterwarningsini選項配置的過濾器。

你可以通過使用filterwarnings標記作為類裝飾器或通過設置pytestmark變量將模塊中的所有測試應用於類的所有測試:

# turns all warnings into errors for this module
pytestmark = pytest.mark.filterwarnings("error")

積分轉到Florian Schulze獲取[pytest-warnings插件中的參考實現

禁用警告摘要

雖然不推薦,但你可以使用--disable-warnings命令行選項從測試運行輸出中完全禁止警告摘要。

完全禁用警告捕獲

此插件默認啟用,但可以在你的pytest.ini文件中完全禁用:

[pytest]
addopts = -p no:warnings

或者傳入命令行。如果測試套件使用外部系統處理警告,這可能很有用。-pno:warnings

棄用警告和待命記錄警告

版本3.8中的新函數。

在3.9版中更改。

默認情況下,pytest將顯示DeprecationWarningPendingDeprecationWarning從用戶代碼和第三方庫警告,建議[PEP-0565。這有助於用戶保持代碼現代化,並在有效刪除已棄用的警告時避免破壞。

有時隱藏在你無法控制的代碼(例如第三方庫)中發生的某些特定棄用警告很有用,在這種情況下,你可以使用警告過濾器選項(ini或標記)來忽略這些警告。

例如:

[pytest]
filterwarnings =
 ignore:.*U.*mode is deprecated:DeprecationWarning

這將忽略DeprecationWarning消息開頭與正則表達式匹配的所有類型的警告。".*U.*modeisdeprecated"

注意

如果在解釋器級別配置警告,使用[PYTHONWARNINGS環境變量或-W命令行選項,pytest將默認不配置任何過濾器。

此外,pytest不遵循PEP-0506重置所有警告過濾器的建議,因為它可能會破壞通過調用自行配置警告過濾器的測試套件`warnings.simplefilter(請參閱問題[#2430以獲取該示例)。

確保代碼觸發棄用警告

你還可以調用全局幫助程序來檢查某個函數調用是否觸發aDeprecationWarningPendingDeprecationWarning

import pytest

def test_global():
    pytest.deprecated_call(myfunction,17)

默認情況下,DeprecationWarningPendingDeprecationWarning不會被使用時,捕捉pytest.warnsrecwarn因為默認的Python警告過濾器隱藏起來。如果你希望在自己的代碼中記錄它們,請使用以下命令warnings.simplefilter('always')

import warnings
import pytest

def test_deprecation(recwarn):
    warnings.simplefilter("always")
    warnings.warn("deprecated",DeprecationWarning)
    assert len(recwarn) == 1
    assert recwarn.pop(DeprecationWarning)

你還可以將其用作上下文管理器:

def test_global():
    with pytest.deprecated_call():
        myobject.deprecated_method()

用警告函數斷言警告

版本2.8中的新函數。

你可以檢查代碼是否引發了特定警告pytest.warns,其工作方式類似於[引發:

import warnings
import pytest

def test_warning():
    with pytest.warns(UserWarning):
        warnings.warn("my warning",UserWarning)

如果未提出相關警告,測試將失敗。match斷言異常與文本或正則表達式匹配的關鍵字參數:

>>> with warns(UserWarning,match='must be 0 or None'):
...    warnings.warn("value must be 0 or None",UserWarning)

>>> with warns(UserWarning,match=r'must be \d+/pre>):
...    warnings.warn("value must be 42",UserWarning)

>>> with warns(UserWarning,match=r'must be \d+/pre>):
...    warnings.warn("this is not here",UserWarning)
Traceback (most recent call last):
  ...
Failed: DID NOT WARN. No warnings of type ...UserWarning... was emitted...

你還可以調用pytest.warns函數或代碼字符串:

pytest.warns(expected_warning,func,*args,**kwargs)
pytest.warns(expected_warning,"func(*args,**kwargs)")

該函數還返回所有引發警告(作為warnings.WarningMessage對象)的列表,你可以查詢其他信息:

with pytest.warns(RuntimeWarning) as record:
    warnings.warn("another warning",RuntimeWarning)

# check that only one warning was raised
assert len(record) == 1
# check that the message matches
assert record[0].message.args[0] == "another warning"

或者,你可以使用[recwarnFixture方法詳細檢查凸起的警告(見下文)。

注意

DeprecationWarning並且PendingDeprecationWarning區別對待;請參閱[確保代碼觸發棄用警告。

錄制警告

你可以使用Fixture方法pytest.warns或使用recwarnFixture方法記錄凸起的警告。

要在pytest.warns不聲明任何有關警告的情況下進行記錄,請傳遞None為預期的警告類型:

with pytest.warns(None) as record:
    warnings.warn("user",UserWarning)
    warnings.warn("runtime",RuntimeWarning)

assert len(record) == 2
assert str(record[0].message) == "user"
assert str(record[1].message) == "runtime"

recwarnFixture方法將記錄整個函數的警告:

import warnings

def test_hello(recwarn):
    warnings.warn("hello",UserWarning)
    assert len(recwarn) == 1
    w = recwarn.pop(UserWarning)
    assert issubclass(w.category,UserWarning)
    assert str(w.message) == "hello"
    assert w.filename
    assert w.lineno

雙方recwarnpytest.warns返回相同的接口,用於記錄警告:一個WarningsRecorder實例。要查看記錄的警告,你可以迭代此實例,調用len它以獲取已記錄警告的數量,或將其編入索引以獲取特定記錄的警告。

完整的API :WarningsRecorder.

自定義失敗消息

記錄警告提供了在未發出警告或滿足其他條件時生成自定義測試失敗消息的機會。

def test():
    with pytest.warns(Warning) as record:
        f()
        if not record:
            pytest.fail("Expected a warning!")

如果在呼叫時沒有發出警告f,那么將評估為。然后,你可以使用自定義錯誤消息進行調用。notrecord``True``pytest.fail

內部pytest警告

版本3.8中的新函數。

pytest可能會在某些情況下生成自己的警告,例如使用不當或不推薦使用的函數。

例如,如果遇到匹配python_classes但也定義__init__構造函數的類,pytest將發出警告,因為這會阻止實例化類:

# content of 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:

-- Docs: https://docs.pytest.org/en/latest/warnings.html
1 warnings in 0.12 seconds

可以使用用於過濾其他類型警告的相同內置機制來過濾這些警告。

請閱讀我們的[向后兼容性政策,了解我們如何繼續棄用並最終刪除函數。

pytest使用以下警告類型,它們是公共API的一部分:

classPytestWarning
基類:UserWarning pytest發出的所有警告的基類。

classPytestDeprecationWarning
基類:pytest.PytestWarning 將來版本中將刪除的函數的警告類。

classRemovedInPytest4Warning
基類:pytest.PytestDeprecationWarning 計划在pytest 4.0中刪除的函數的警告類。

classPytestExperimentalApiWarning
基類:pytest.PytestWarning 警告類別用於表示pytest中的實驗。謹慎使用,因為API可能會在未來版本中更改甚至完全刪除\


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM