目錄:
- 安裝及入門(mén)
- 使用和調(diào)用方法
- 原有TestSuite使用方法
- 斷言的編寫(xiě)和報(bào)告
- Pytest fixtures:清晰 模塊化 易擴(kuò)展
- 使用Marks標(biāo)記測(cè)試用例
- Monkeypatching/對(duì)模塊和環(huán)境進(jìn)行Mock
- 使用tmp目錄和文件
- 捕獲stdout及stderr輸出
- 捕獲警告信息
- 模塊及測(cè)試文件中集成doctest測(cè)試
- skip及xfail: 處理不能成功的測(cè)試用例
- Fixture方法及測(cè)試用例的參數(shù)化
- 緩存: 使用跨執(zhí)行狀態(tài)
- unittest.TestCase支持
- 運(yùn)行Nose用例
- 經(jīng)典xUnit風(fēng)格的setup/teardown
- 安裝和使用插件
- 插件編寫(xiě)
- 編寫(xiě)鉤子(hook)方法
- 運(yùn)行日志
- API參考
- 優(yōu)質(zhì)集成實(shí)踐
- 片狀測(cè)試
- Pytest導(dǎo)入機(jī)制及sys.path/PYTHONPATH
- 配置選項(xiàng)
- 示例及自定義技巧
- 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ì)算并列出skip和xfail測(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)
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)記。
或者,你可以使用條件字符串而不是布爾值,但它們不能在模塊之間輕松共享,因此主要出于向后兼容性原因支持它們。
跳過(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è)試用例的快速指南:
- 無(wú)條件地跳過(guò)模塊中的所有測(cè)試用例:
pytestmark = pytest.mark.skip("all tests still WIP")
- 根據(jù)某些條件跳過(guò)模塊中的所有測(cè)試用例:
pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="tests for linux only")
- 如果缺少某些導(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)的。
strict參數(shù)
版本2.9中的新功能。
雙方XFAIL并XPASS除非不失敗的測(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è)異?;虍惓TM。
@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```