[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