[TOC]html
返回: Pytest權威教程python
跳過(Skip)及預期失敗(xFail): 處理不能成功的測試用例
你能夠標記沒法在某些平臺上運行的測試用例或你但願失敗的測試用例,以便Pytest能夠相應地處理它們並提供測試會話的摘要,同時保持測試套件爲經過狀態。linux
跳過(Skip)指,你但願若是某些條件獲得知足你的測試用例才執行,不然Pytest應該徹底跳過運行該用例。常見示例是在非Windows平臺上跳過僅限Windows的測試用例,或者跳過依賴於當前不可用的外部資源的測試用例(例如數據庫)。數據庫
預期失敗(xFail)意味着已知測試失敗並標記緣由。一個常見的例子是對還沒有實現的函數的測試,或者還沒有修復的錯誤。當測試經過時儘管預計會失敗(標記爲pytest.mark.xfail
),但它將在測試結果摘要及報告中顯示爲xpass狀態。bash
Pytest分別計算並列出Skip和xFail用例。默認狀況下不顯示有關跳過/標記失敗用例的詳細信息,以免輸出混亂。你可使用該-r
選項查看與測試進度中顯示的不一樣字母參數對應的詳細信息:session
pytest -rxXs # 顯示跳過skipped、指望失敗xfailed、非指望成功xpass狀態用例的額外信息
-r
能夠經過運行pytest -h,找到有關該選項的更多詳細信息。函數
(請參閱:如何更改命令行選項默認值)測試
Skip跳過用例
版本2.9中的新函數。url
跳過測試用例的最簡單方法是使用skip裝飾器標記它,能夠傳遞一個可選的緣由reason參數:spa
@pytest.mark.skip(reason="目前沒辦法測試該用例") def test_the_unknown(): ...
或者,也能夠在測試執行或setup期間,經過調用pytest.skip(reason)函數強制跳過該用例:
def test_function(): if not valid_config(): pytest.skip("不支持該配置")
當在導入時間內沒法評估跳過條件時,這種在用例跳過的方法很是有用。
也能夠在模塊級別跳過整個模塊:pytest.skip(reason,allow_module_level=True)
import sys import pytest if not sys.platform.startswith("win"): pytest.skip("跳過只支持Windows平臺的用意",allow_module_level=True)
(譯者注:使用此方法跳過整個模塊時會拋出Skipped異常,若是在腳本下方使用pytest.main()執行,會執行不到。此時應使用命令行pytest命令執行。) 參考: pytest.mark.skip
Skipif:指定條件下跳過
2.0版中的新功能。
若是你但願特定條件地跳過某些用例,則可使用skipif。下面的示例演示了,當Python版本小於3.6時跳過測試用例。
import sys import pytest @pytest.mark.skipif(sys.version_info<(3,6),reason="須要Python3.6版本以上") def test_function(): ...
(譯者注:skipif方法必須指定reason)
若是收集用例時,skipif中的條件表達式計算爲True,則將跳過測試函數,運行是使用會在-rs
,會在運行結果摘要中顯示指定的緣由。
你能夠skipif在模塊之間共享標記,參考如下測試腳本:
# test_mymodule.py模塊內容 import mymodule minversion = pytest.mark.skipif( mymodule.__versioninfo__ < (1,1),reason="至少mymodule-1.1版本以上" ) @minversion def test_function(): ...
你能夠導入mark標記並在另外一個測試模塊中重複使用它:
# test_myothermodule.py from test_mymodule import minversion @minversion def test_anotherfunction(): ...
對於較大的測試套件,一般最好有一個文件來定義標記,而後在整個測試套件中一致地應用這些標記。
或者,你可使用條件字符串而不是布爾值,但它們不能在模塊之間輕鬆共享,所以主要出於向後兼容性緣由來支持它們。
參考: pytest.mark.skipif
跳過類或模塊的全部測試用例
你能夠skipif在類上使用標記(與任何其餘標記同樣):
@pytest.mark.skipif(sys.platform=="win32",reason="不在Windows系統運行") class TestPosixCalls(object): def test_function(self): "在Win32平臺不執行setup和該測試方法"
若是skipif的條件是True,則該類的每一個測試用例都將自動跳過。
若是要跳過模塊的全部測試用例,能夠經過在模塊中聲明pytestmark變量來使用:
# test_module.py pytestmark = pytest.mark.skipif(...)
若是用例使用了多個skipif裝飾器時,任意一個跳過條件爲真,則將跳過該用例。
跳過文件或目錄
有時你可能須要跳過整個文件或目錄,例如,若是測試依賴於Python版本特定的函數或包含你不但願運行Pytest的代碼。在這種狀況下,你必須從測試集合中排除文件和目錄。有關更多信息,請參閱:自定義測試集合。
跳過缺乏的導入依賴關係
你能夠在模塊級別或測試或測試setup方法中使用如下幫助程序:
docutils = pytest.importorskip("docutils")
若是docutils沒法在此處導入,則會致使測試跳過結果。你還能夠根據庫的版本號跳過:
docutils = pytest.importorskip("docutils",minversion="0.3")
將從指定模塊的__version__屬性中讀取版本。
摘要
如下是如何在不一樣狀況下跳過模塊中的測試用例的快速指南:
- 無條件地跳過模塊中的全部測試用例如:
pytestmark = pytest.mark.skip("全部用例還在開發中")
- 根據某些條件跳過模塊中的全部測試用例如:
pytestmark = pytest.mark.skipif(sys.platform == "win32",reason="tests for linux only")
- 若是缺乏某些導入,則跳過模塊中的全部測試用例如:
pexpect = pytest.importorskip("pexpect")
xFail:將測試函數標記爲預期失敗
你可使用xfail標記指示你但願測試失敗:
@pytest.mark.xfail def test_function(): ...
將運行此測試,但在失敗時不會報告回溯。相反,終端報告會將其列在「預期失敗」(XFAIL
)或「意外傳遞」(XPASS
)部分中。
或者,你也能夠xfail在測試用例或setup函數中強制標記測試預期失敗:
def test_function(): if not valid_config(): pytest.xfail("failing configuration (but should work)")
這將無條件地製做test_function``XFAIL
。請注意,pytest.xfail
調用後不會執行其餘代碼,與標記不一樣。那是由於它是經過引起已知異常在內部實現的。
參考: pytest.mark.xfail
strict參數
版本2.9中的新函數。
若是strict參數設置爲True, 若是出現xpass,測試套件的結果將視爲失敗。:
@pytest.mark.xfail(strict=True) def test_function(): ...
這將致使`xpass(「意外經過」)此測試的結果致使測試套件失敗。
strict參數也可使用xfail_strict變量配置到pytest.ini文件中。:
[pytest] xfail_strict=true
reason參數
與skipif同樣,你也能夠在特定平臺上標記你對失敗的指望:
@pytest.mark.xfail(sys.version_info >= (3,6),reason="Python3.6 API變動") def test_function(): ...
raises參數
若是你想更具體地說明測試失敗的緣由,能夠在raises
參數中指定單個異常或異常元組。
@pytest.mark.xfail(raises=RuntimeError) def test_function(): ...
而後,若是測試失敗而且沒有提到的例外,那麼測試將被報告爲常規失敗raises
。
run參數
若是測試應標記爲xfail而且如此報告但不該該執行,請使用如下run
參數False
:
@pytest.mark.xfail(run=False) def test_function(): ...
這對於崩潰解釋器的xfailing測試特別有用,應該稍後進行調查。
忽略xfail
經過在命令行上指定:
pytest --runxfail
你能夠強制運行並報告xfail
標記的測試,就像它根本沒有標記同樣。這也致使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 =========================
Skip/xFail參數設置
使用參數化時,能夠將skip和xfail等標記應用於各個測試實例如:
import pytest import sys @pytest.mark.parametrize( ("n","expected"), [ (1,2), pytest.param(1,0,marks=pytest.mark.xfail), pytest.param(1,3,marks=pytest.mark.xfail(reason="某個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