Pytest官方教程-12-skip及xfail: 處理不能成功的測(cè)試用例

目錄:

  1. 安裝及入門(mén)
  2. 使用和調(diào)用方法
  3. 原有TestSuite使用方法
  4. 斷言的編寫(xiě)和報(bào)告
  5. Pytest fixtures:清晰 模塊化 易擴(kuò)展
  6. 使用Marks標(biāo)記測(cè)試用例
  7. Monkeypatching/對(duì)模塊和環(huán)境進(jìn)行Mock
  8. 使用tmp目錄和文件
  9. 捕獲stdout及stderr輸出
  10. 捕獲警告信息
  11. 模塊及測(cè)試文件中集成doctest測(cè)試
  12. skip及xfail: 處理不能成功的測(cè)試用例
  13. Fixture方法及測(cè)試用例的參數(shù)化
  14. 緩存: 使用跨執(zhí)行狀態(tài)
  15. unittest.TestCase支持
  16. 運(yùn)行Nose用例
  17. 經(jīng)典xUnit風(fēng)格的setup/teardown
  18. 安裝和使用插件
  19. 插件編寫(xiě)
  20. 編寫(xiě)鉤子(hook)方法
  21. 運(yùn)行日志
  22. API參考
    1. 方法(Functions)
    2. 標(biāo)記(Marks)
    3. 鉤子(Hooks)
    4. 裝置(Fixtures)
    5. 對(duì)象(Objects)
    6. 特殊變量(Special Variables)
    7. 環(huán)境變量(Environment Variables)
    8. 配置選項(xiàng)(Configuration Options)
  23. 優(yōu)質(zhì)集成實(shí)踐
  24. 片狀測(cè)試
  25. Pytest導(dǎo)入機(jī)制及sys.path/PYTHONPATH
  26. 配置選項(xiàng)
  27. 示例及自定義技巧
  28. Bash自動(dòng)補(bǔ)全設(shè)置

skip及xfail: 處理不能成功的測(cè)試用例

你可以標(biāo)記無(wú)法在某些平臺(tái)上運(yùn)行的測(cè)試用例或你希望失敗的測(cè)試用例,以便pytest可以相應(yīng)地處理它們并提供測(cè)試會(huì)話的摘要,同時(shí)保持測(cè)試套件為通過(guò)狀態(tài)。

一個(gè)Skip意味著你希望如果某些條件得到滿(mǎn)足你的測(cè)試才執(zhí)行,否則pytest應(yīng)該完全跳過(guò)運(yùn)行該用例。常見(jiàn)示例是在非Windows平臺(tái)上跳過(guò)僅限Windows的測(cè)試用例,或者跳過(guò)依賴(lài)于當(dāng)前不可用的外部資源的測(cè)試用例(例如數(shù)據(jù)庫(kù))。

一個(gè)xfail意味著已知測(cè)試失敗并標(biāo)記原因。一個(gè)常見(jiàn)的例子是對(duì)尚未實(shí)現(xiàn)的功能的測(cè)試,或者尚未修復(fù)的錯(cuò)誤。當(dāng)測(cè)試通過(guò)時(shí)盡管預(yù)計(jì)會(huì)失?。?biāo)記為pytest.mark.xfail),但它在并將在測(cè)試摘要及報(bào)告中顯示為xpass*.

pytest分別計(jì)算并列出skipxfail測(cè)試。默認(rèn)情況下不顯示有關(guān)skip/ xfailed測(cè)試的詳細(xì)信息,以避免輸出混亂。你可以使用該-r選項(xiàng)查看與測(cè)試進(jìn)度中顯示的“短”字母對(duì)應(yīng)的詳細(xì)信息:

pytest -rxXs  # show extra info on xfailed, xpassed, and skipped tests

-r可以通過(guò)運(yùn)行找到有關(guān)該選項(xiàng)的更多詳細(xì)信息。pytest -h

(請(qǐng)參閱如何更改命令行選項(xiàng)默認(rèn)值

跳過(guò)測(cè)試用例

版本2.9中的新功能。

跳過(guò)測(cè)試用例的最簡(jiǎn)單方法是使用skip裝飾器標(biāo)記它,可以傳遞一個(gè)可選的reason

@pytest.mark.skip(reason="no way of currently testing this")
def test_the_unknown():
    ...

或者,也可以通過(guò)調(diào)用pytest.skip(reason)函數(shù)在測(cè)試執(zhí)行或設(shè)置期間強(qiáng)制跳過(guò):

def test_function():
    if not valid_config():
        pytest.skip("unsupported configuration")

當(dāng)在導(dǎo)入時(shí)間內(nèi)無(wú)法評(píng)估跳過(guò)條件時(shí),命令性方法很有用。

也可以在模塊級(jí)別跳過(guò)整個(gè)模塊 :pytest.skip(reason, allow_module_level=True)

import sys
import pytest

if not sys.platform.startswith("win"):
    pytest.skip("skipping windows-only tests", allow_module_level=True)

參考pytest.mark.skip

skipif

2.0版中的新功能。

如果你希望有條件地跳過(guò)某些內(nèi)容,則可以使用skipif。下面是一個(gè)標(biāo)記在Python3.6之前的解釋器上運(yùn)行時(shí)要跳過(guò)的測(cè)試函數(shù)的示例:

import sys

@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
def test_function():
    ...

如果條件True在收集期間評(píng)估為,則將跳過(guò)測(cè)試函數(shù),使用時(shí)會(huì)在摘要中顯示指定的原因-rs

你可以skipif在模塊之間共享標(biāo)記??紤]這個(gè)測(cè)試模塊:

# content of test_mymodule.py
import mymodule

minversion = pytest.mark.skipif(
    mymodule.__versioninfo__ < (1, 1), reason="at least mymodule-1.1 required"
)

@minversion
def test_function():
    ...

你可以導(dǎo)入mark標(biāo)記并在另一個(gè)測(cè)試模塊中重復(fù)使用它:

# test_myothermodule.py
from test_mymodule import minversion

@minversion
def test_anotherfunction():
    ...

對(duì)于較大的測(cè)試套件,通常最好有一個(gè)文件來(lái)定義標(biāo)記,然后在整個(gè)測(cè)試套件中一致地應(yīng)用這些標(biāo)記。

或者,你可以使用條件字符串而不是布爾值,但它們不能在模塊之間輕松共享,因此主要出于向后兼容性原因支持它們。

參考pytest.mark.skipif

跳過(guò)類(lèi)或模塊的所有測(cè)試用例

你可以skipif在類(lèi)上使用標(biāo)記(與任何其他標(biāo)記一樣):

@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
class TestPosixCalls(object):
    def test_function(self):
        "will not be setup or run under 'win32' platform"

如果條件是True,則此標(biāo)記將為該類(lèi)的每個(gè)測(cè)試方法生成跳過(guò)結(jié)果。

如果要跳過(guò)模塊的所有測(cè)試用例,可以pytestmark在全局級(jí)別使用該名稱(chēng):

# test_module.py
pytestmark = pytest.mark.skipif(...)

如果將多個(gè)skipif裝飾器應(yīng)用于測(cè)試用例,則如果任何跳過(guò)條件為真,則將跳過(guò)該裝飾器。

跳過(guò)文件或目錄

有時(shí)你可能需要跳過(guò)整個(gè)文件或目錄,例如,如果測(cè)試依賴(lài)于Python版本特定的功能或包含你不希望運(yùn)行pytest的代碼。在這種情況下,你必須從集合中排除文件和目錄。有關(guān)更多信息,請(qǐng)參閱自定義測(cè)試集合

跳過(guò)缺少的導(dǎo)入依賴(lài)關(guān)系

你可以在模塊級(jí)別或測(cè)試或測(cè)試setup方法中使用以下幫助程序:

docutils = pytest.importorskip("docutils")

如果docutils無(wú)法在此處導(dǎo)入,則會(huì)導(dǎo)致測(cè)試跳過(guò)結(jié)果。你還可以根據(jù)庫(kù)的版本號(hào)跳過(guò):

docutils = pytest.importorskip("docutils", minversion="0.3")

將從指定模塊的__version__屬性中讀取版本。

摘要

以下是如何在不同情況下跳過(guò)模塊中的測(cè)試用例的快速指南:

  1. 無(wú)條件地跳過(guò)模塊中的所有測(cè)試用例:
pytestmark = pytest.mark.skip("all tests still WIP")
  1. 根據(jù)某些條件跳過(guò)模塊中的所有測(cè)試用例:
pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="tests for linux only")
  1. 如果缺少某些導(dǎo)入,則跳過(guò)模塊中的所有測(cè)試用例:
pexpect = pytest.importorskip("pexpect")

XFail:將測(cè)試函數(shù)標(biāo)記為預(yù)期失敗

你可以使用xfail標(biāo)記指示你希望測(cè)試失?。?/p>

@pytest.mark.xfail
def test_function():
    ...

將運(yùn)行此測(cè)試,但在失敗時(shí)不會(huì)報(bào)告回溯。相反,終端報(bào)告會(huì)將其列在“預(yù)期失敗”(XFAIL)或“意外傳遞”(XPASS)部分中。

或者,你也可以XFAIL在測(cè)試或設(shè)置功能中強(qiáng)制標(biāo)記測(cè)試:

def test_function():
    if not valid_config():
        pytest.xfail("failing configuration (but should work)")

這將無(wú)條件地制作test_function XFAIL。請(qǐng)注意,pytest.xfail調(diào)用后不會(huì)執(zhí)行其他代碼,與標(biāo)記不同。那是因?yàn)樗峭ㄟ^(guò)引發(fā)已知異常在內(nèi)部實(shí)??現(xiàn)的。

參考pytest.mark.xfail

strict參數(shù)

版本2.9中的新功能。

雙方XFAILXPASS除非不失敗的測(cè)試套件,strict只有關(guān)鍵字的參數(shù)作為傳遞True

@pytest.mark.xfail(strict=True)
def test_function():
    ...

這將導(dǎo)致XPASS(“意外通過(guò)”)此測(cè)試的結(jié)果導(dǎo)致測(cè)試套件失敗。

你可以strict使用xfail_strictini選項(xiàng)更改參數(shù) 的默認(rèn)值:

[pytest]
xfail_strict=true

reason參數(shù)

skipif一樣,你也可以在特定平臺(tái)上標(biāo)記你對(duì)失敗的期望:

= (3, 6), reason="python3.6 api changes")
def test_function():
    ...

raises參數(shù)

如果你想更具體地說(shuō)明測(cè)試失敗的原因,可以在raises參數(shù)中指定單個(gè)異?;虍惓TM。

@pytest.mark.xfail(raises=RuntimeError)
def test_function():
    ...

然后,如果測(cè)試失敗并且沒(méi)有提到的例外,那么測(cè)試將被報(bào)告為常規(guī)失敗raises。

run參數(shù)

如果測(cè)試應(yīng)標(biāo)記為xfail并且如此報(bào)告但不應(yīng)該執(zhí)行,請(qǐng)使用以下run參數(shù)False

@pytest.mark.xfail(run=False)
def test_function():
    ...

這對(duì)于崩潰解釋器的xfailing測(cè)試特別有用,應(yīng)該稍后進(jìn)行調(diào)查。

忽略xfail

通過(guò)在命令行上指定:

pytest --runxfail

你可以強(qiáng)制運(yùn)行并報(bào)告xfail標(biāo)記的測(cè)試,就像它根本沒(méi)有標(biāo)記一樣。這也導(dǎo)致pytest.xfail沒(méi)有效果。

示例

這是一個(gè)簡(jiǎn)單的測(cè)試文件,有幾個(gè)用法:

import pytest

xfail = pytest.mark.xfail

@xfail
def test_hello():
    assert 0

@xfail(run=False)
def test_hello2():
    assert 0

@xfail("hasattr(os, 'sep')")
def test_hello3():
    assert 0

@xfail(reason="bug 110")
def test_hello4():
    assert 0

@xfail('pytest.__version__[0] != "17"')
def test_hello5():
    assert 0

def test_hello6():
    pytest.xfail("reason")

@xfail(raises=IndexError)
def test_hello7():
    x = []
    x[1] = 1

使用report-on-xfail選項(xiàng)運(yùn)行它會(huì)提供以下輸出:

example $ pytest -rx xfail_demo.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/example
collected 7 items

xfail_demo.py xxxxxxx                                                [100%]
========================= short test summary info ==========================
XFAIL xfail_demo.py::test_hello
XFAIL xfail_demo.py::test_hello2
  reason: [NOTRUN]
XFAIL xfail_demo.py::test_hello3
  condition: hasattr(os, 'sep')
XFAIL xfail_demo.py::test_hello4
  bug 110
XFAIL xfail_demo.py::test_hello5
  condition: pytest.__version__[0] != "17"
XFAIL xfail_demo.py::test_hello6
  reason: reason
XFAIL xfail_demo.py::test_hello7

======================== 7 xfailed in 0.12 seconds =========================

跳過(guò)/ xfail與參數(shù)多態(tài)

使用參數(shù)化時(shí),可以將skip和xfail等標(biāo)記應(yīng)用于各個(gè)測(cè)試實(shí)例:

import pytest

@pytest.mark.parametrize(
    ("n", "expected"),
    [
        (1, 2),
        pytest.param(1, 0, marks=pytest.mark.xfail),
        pytest.param(1, 3, marks=pytest.mark.xfail(reason="some bug")),
        (2, 3),
        (3, 4),
        (4, 5),
        pytest.param(
            10, 11, marks=pytest.mark.skipif(sys.version_info >= (3, 0), reason="py2k")
        ),
    ],
)
def test_increment(n, expected):
    assert n + 1 == expected```
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容