目錄:
- 安裝及入門
- 使用和調(diào)用方法
- 原有TestSuite使用方法
- 斷言的編寫和報告
- Pytest fixtures:清晰 模塊化 易擴展
- 使用Marks標(biāo)記測試用例
- Monkeypatching/對模塊和環(huán)境進(jìn)行Mock
- 使用tmp目錄和文件
- 捕獲stdout及stderr輸出
- 捕獲警告信息
- 模塊及測試文件中集成doctest測試
- skip及xfail: 處理不能成功的測試用例
- Fixture方法及測試用例的參數(shù)化
- 緩存: 使用跨執(zhí)行狀態(tài)
- unittest.TestCase支持
- 運行Nose用例
- 經(jīng)典xUnit風(fēng)格的setup/teardown
- 安裝和使用插件
- 插件編寫
- 編寫鉤子(hook)方法
- 運行日志
- API參考
- 優(yōu)質(zhì)集成實踐
- 片狀測試
- Pytest導(dǎo)入機制及sys.path/PYTHONPATH
- 配置選項
- 示例及自定義技巧
- Bash自動補全設(shè)置
skip及xfail: 處理不能成功的測試用例
你可以標(biāo)記無法在某些平臺上運行的測試用例或你希望失敗的測試用例,以便pytest可以相應(yīng)地處理它們并提供測試會話的摘要,同時保持測試套件為通過狀態(tài)。
一個Skip意味著你希望如果某些條件得到滿足你的測試才執(zhí)行,否則pytest應(yīng)該完全跳過運行該用例。常見示例是在非Windows平臺上跳過僅限Windows的測試用例,或者跳過依賴于當(dāng)前不可用的外部資源的測試用例(例如數(shù)據(jù)庫)。
一個xfail意味著已知測試失敗并標(biāo)記原因。一個常見的例子是對尚未實現(xiàn)的功能的測試,或者尚未修復(fù)的錯誤。當(dāng)測試通過時盡管預(yù)計會失敗(標(biāo)記為pytest.mark.xfail
),但它在并將在測試摘要及報告中顯示為xpass*.
pytest
分別計算并列出skip和xfail測試。默認(rèn)情況下不顯示有關(guān)skip/ xfailed測試的詳細(xì)信息,以避免輸出混亂。你可以使用該-r
選項查看與測試進(jìn)度中顯示的“短”字母對應(yīng)的詳細(xì)信息:
pytest -rxXs # show extra info on xfailed, xpassed, and skipped tests
-r
可以通過運行找到有關(guān)該選項的更多詳細(xì)信息。pytest -h
(請參閱如何更改命令行選項默認(rèn)值)
跳過測試用例
版本2.9中的新功能。
跳過測試用例的最簡單方法是使用skip
裝飾器標(biāo)記它,可以傳遞一個可選的reason
:
@pytest.mark.skip(reason="no way of currently testing this")
def test_the_unknown():
...
或者,也可以通過調(diào)用pytest.skip(reason)
函數(shù)在測試執(zhí)行或設(shè)置期間強制跳過:
def test_function():
if not valid_config():
pytest.skip("unsupported configuration")
當(dāng)在導(dǎo)入時間內(nèi)無法評估跳過條件時,命令性方法很有用。
也可以在模塊級別跳過整個模塊 :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)
skipif
2.0版中的新功能。
如果你希望有條件地跳過某些內(nèi)容,則可以使用skipif
。下面是一個標(biāo)記在Python3.6之前的解釋器上運行時要跳過的測試函數(shù)的示例:
import sys
@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
def test_function():
...
如果條件True
在收集期間評估為,則將跳過測試函數(shù),使用時會在摘要中顯示指定的原因-rs
。
你可以skipif
在模塊之間共享標(biāo)記。考慮這個測試模塊:
# 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)記并在另一個測試模塊中重復(fù)使用它:
# test_myothermodule.py
from test_mymodule import minversion
@minversion
def test_anotherfunction():
...
對于較大的測試套件,通常最好有一個文件來定義標(biāo)記,然后在整個測試套件中一致地應(yīng)用這些標(biāo)記。
或者,你可以使用條件字符串而不是布爾值,但它們不能在模塊之間輕松共享,因此主要出于向后兼容性原因支持它們。
跳過類或模塊的所有測試用例
你可以skipif
在類上使用標(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)記將為該類的每個測試方法生成跳過結(jié)果。
如果要跳過模塊的所有測試用例,可以pytestmark
在全局級別使用該名稱:
# test_module.py
pytestmark = pytest.mark.skipif(...)
如果將多個skipif
裝飾器應(yīng)用于測試用例,則如果任何跳過條件為真,則將跳過該裝飾器。
跳過文件或目錄
有時你可能需要跳過整個文件或目錄,例如,如果測試依賴于Python版本特定的功能或包含你不希望運行pytest的代碼。在這種情況下,你必須從集合中排除文件和目錄。有關(guān)更多信息,請參閱自定義測試集合。
跳過缺少的導(dǎo)入依賴關(guān)系
你可以在模塊級別或測試或測試setup方法中使用以下幫助程序:
docutils = pytest.importorskip("docutils")
如果docutils
無法在此處導(dǎo)入,則會導(dǎo)致測試跳過結(jié)果。你還可以根據(jù)庫的版本號跳過:
docutils = pytest.importorskip("docutils", minversion="0.3")
將從指定模塊的__version__
屬性中讀取版本。
摘要
以下是如何在不同情況下跳過模塊中的測試用例的快速指南:
- 無條件地跳過模塊中的所有測試用例:
pytestmark = pytest.mark.skip("all tests still WIP")
- 根據(jù)某些條件跳過模塊中的所有測試用例:
pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="tests for linux only")
- 如果缺少某些導(dǎo)入,則跳過模塊中的所有測試用例:
pexpect = pytest.importorskip("pexpect")
XFail:將測試函數(shù)標(biāo)記為預(yù)期失敗
你可以使用xfail
標(biāo)記指示你希望測試失敗:
@pytest.mark.xfail
def test_function():
...
將運行此測試,但在失敗時不會報告回溯。相反,終端報告會將其列在“預(yù)期失敗”(XFAIL
)或“意外傳遞”(XPASS
)部分中。
或者,你也可以XFAIL
在測試或設(shè)置功能中強制標(biāo)記測試:
def test_function():
if not valid_config():
pytest.xfail("failing configuration (but should work)")
這將無條件地制作test_function
XFAIL
。請注意,pytest.xfail
調(diào)用后不會執(zhí)行其他代碼,與標(biāo)記不同。那是因為它是通過引發(fā)已知異常在內(nèi)部實??現(xiàn)的。
strict
參數(shù)
版本2.9中的新功能。
雙方XFAIL
并XPASS
除非不失敗的測試套件,strict
只有關(guān)鍵字的參數(shù)作為傳遞True
:
@pytest.mark.xfail(strict=True)
def test_function():
...
這將導(dǎo)致XPASS
(“意外通過”)此測試的結(jié)果導(dǎo)致測試套件失敗。
你可以strict
使用xfail_strict
ini選項更改參數(shù) 的默認(rèn)值:
[pytest]
xfail_strict=true
reason
參數(shù)
與skipif一樣,你也可以在特定平臺上標(biāo)記你對失敗的期望:
= (3, 6), reason="python3.6 api changes")
def test_function():
...
raises
參數(shù)
如果你想更具體地說明測試失敗的原因,可以在raises
參數(shù)中指定單個異常或異常元組。
@pytest.mark.xfail(raises=RuntimeError)
def test_function():
...
然后,如果測試失敗并且沒有提到的例外,那么測試將被報告為常規(guī)失敗raises
。
run
參數(shù)
如果測試應(yīng)標(biāo)記為xfail并且如此報告但不應(yīng)該執(zhí)行,請使用以下run
參數(shù)False
:
@pytest.mark.xfail(run=False)
def test_function():
...
這對于崩潰解釋器的xfailing測試特別有用,應(yīng)該稍后進(jìn)行調(diào)查。
忽略xfail
通過在命令行上指定:
pytest --runxfail
你可以強制運行并報告xfail
標(biāo)記的測試,就像它根本沒有標(biāo)記一樣。這也導(dǎo)致pytest.xfail
沒有效果。
示例
這是一個簡單的測試文件,有幾個用法:
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選項運行它會提供以下輸出:
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 =========================
跳過/ xfail與參數(shù)多態(tài)
使用參數(shù)化時,可以將skip和xfail等標(biāo)記應(yīng)用于各個測試實例:
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```