你可以标记无法在某些平台上运行的测试用例或你希望失败的测试用例,以便Pytest可以相应地处理它们并提供测试会话的摘要,同时保持测试套件为通过状态。
跳过(Skip)指,你希望如果某些条件得到满足你的测试用例才执行,否则Pytest应该完全跳过运行该用例。常见示例是在非Windows平台上跳过仅限Windows的测试用例,或者跳过依赖于当前不可用的外部资源的测试用例(例如数据库)。
预期失败(xFail)意味着已知测试失败并标记原因。一个常见的例子是对尚未实现的函数的测试,或者尚未修复的错误。当测试通过时尽管预计会失败(标记为pytest.mark.xfail),但它将在测试结果摘要及报告中显示为xpass状态。
Pytest分别计算并列出Skip和xFail用例。默认情况下不显示有关跳过/标记失败用例的详细信息,以避免输出混乱。你可以使用该-r选项查看与测试进度中显示的不同字母参数对应的详细信息:
Copypytest -rxXs # 显示跳过skipped、期望失败xfailed、非期望成功xpass状态用例的额外信息
-r可以通过运行pytest -h,找到有关该选项的更多详细信息。
(请参阅:如何更改命令行选项默认值)
版本2.9中的新函数。
跳过测试用例的最简单方法是使用skip装饰器标记它,可以传递一个可选的原因reason参数:
[email protected](reason="目前没办法测试该用例")deftest_the_unknown():
...
或者,也可以在测试执行或setup期间,通过调用pytest.skip(reason)函数强制跳过该用例:
Copydeftest_function():
ifnot valid_config():
pytest.skip("不支持该配置")
当在导入时间内无法评估跳过条件时,这种在用例跳过的方法非常有用。
也可以在模块级别跳过整个模块:pytest.skip(reason,allow_module_level=True)
Copyimport sys
import pytest
ifnot sys.platform.startswith("win"):
pytest.skip("跳过只支持Windows平台的用意",allow_module_level=True)
(译者注:使用此方法跳过整个模块时会抛出Skipped异常,如果在脚本下方使用pytest.main()执行,会执行不到。此时应使用命令行pytest命令执行。)
参考: pytest.mark.skip
2.0版中的新功能。
如果你希望特定条件地跳过某些用例,则可以使用skipif。下面的示例演示了,当Python版本小于3.6时跳过测试用例。
Copyimport sys
import pytest
@pytest.mark.skipif(sys.version_info<(3,6),reason="需要Python3.6版本以上")deftest_function():
...
(译者注:skipif方法必须指定reason)
如果收集用例时,skipif中的条件表达式计算为True,则将跳过测试函数,运行是使用会在-rs,会在运行结果摘要中显示指定的原因。
你可以skipif在模块之间共享标记,参考以下测试脚本:
Copy# test_mymodule.py模块内容import mymodule
minversion = pytest.mark.skipif(
mymodule.__versioninfo__ < (1,1),reason="至少mymodule-1.1版本以上"
)
@minversiondeftest_function():
...
你可以导入mark标记并在另一个测试模块中重复使用它:
Copy# test_myothermodule.pyfrom test_mymodule import minversion
@minversiondeftest_anotherfunction():
...
对于较大的测试套件,通常最好有一个文件来定义标记,然后在整个测试套件中一致地应用这些标记。
或者,你可以使用条件字符串而不是布尔值,但它们不能在模块之间轻松共享,因此主要出于向后兼容性原因来支持它们。
参考: pytest.mark.skipif
你可以skipif在类上使用标记(与任何其他标记一样):
[email protected](sys.platform=="win32",reason="不在Windows系统运行")classTestPosixCalls(object):
deftest_function(self):
"在Win32平台不执行setup和该测试方法"
如果skipif的条件是True,则该类的每个测试用例都将自动跳过。
如果要跳过模块的所有测试用例,可以通过在模块中声明pytestmark变量来使用:
Copy# test_module.py
pytestmark = pytest.mark.skipif(...)
如果用例使用了多个skipif装饰器时,任意一个跳过条件为真,则将跳过该用例。
有时你可能需要跳过整个文件或目录,例如,如果测试依赖于Python版本特定的函数或包含你不希望运行Pytest的代码。在这种情况下,你必须从测试集合中排除文件和目录。有关更多信息,请参阅:自定义测试集合。
你可以在模块级别或测试或测试setup方法中使用以下帮助程序:
Copydocutils = pytest.importorskip("docutils")
如果docutils无法在此处导入,则会导致测试跳过结果。你还可以根据库的版本号跳过:
Copydocutils = pytest.importorskip("docutils",minversion="0.3")
将从指定模块的__version__属性中读取版本。
以下是如何在不同情况下跳过模块中的测试用例的快速指南:
无条件地跳过模块中的所有测试用例如:
Copypytestmark = pytest.mark.skip("所有用例还在开发中")
根据某些条件跳过模块中的所有测试用例如:
Copypytestmark = pytest.mark.skipif(sys.platform == "win32",reason="tests for linux only")
如果缺少某些导入,则跳过模块中的所有测试用例如:
Copypexpect = pytest.importorskip("pexpect")
你可以使用xfail标记指示你希望测试失败:
[email protected]_function():
...
将运行此测试,但在失败时不会报告回溯。相反,终端报告会将其列在“预期失败”(XFAIL)或“意外传递”(XPASS)部分中。
或者,你也可以xfail在测试用例或setup函数中强制标记测试预期失败:
Copydeftest_function():
ifnot valid_config():
pytest.xfail("failing configuration (but should work)")
这将无条件地制作test_function``XFAIL。请注意,pytest.xfail调用后不会执行其他代码,与标记不同。那是因为它是通过引发已知异常在内部实现的。
参考: pytest.mark.xfail
版本2.9中的新函数。
如果strict参数设置为True, 如果出现xpass,测试套件的结果将视为失败。:
[email protected](strict=True)deftest_function():
...
这将导致`xpass(“意外通过”)此测试的结果导致测试套件失败。
strict参数也可以使用xfail_strict变量配置到pytest.ini文件中。:
Copy[pytest]xfail_strict=true
与skipif一样,你也可以在特定平台上标记你对失败的期望:
[email protected](sys.version_info >= (3,6),reason="Python3.6 API变更")deftest_function():
...
如果你想更具体地说明测试失败的原因,可以在raises参数中指定单个异常或异常元组。
[email protected](raises=RuntimeError)deftest_function():
...
然后,如果测试失败并且没有提到的例外,那么测试将被报告为常规失败raises。
如果测试应标记为xfail并且如此报告但不应该执行,请使用以下run参数False:
[email protected](run=False)deftest_function():
...
这对于崩溃解释器的xfailing测试特别有用,应该稍后进行调查。
通过在命令行上指定:
Copypytest --runxfail
你可以强制运行并报告xfail标记的测试,就像它根本没有标记一样。这也导致pytest.xfail没有效果。
这是一个简单的测试文件,有几个使用方法:
Copyimport pytest
xfail = pytest.mark.xfail
@xfaildeftest_hello():
assert0@xfail(run=False)deftest_hello2():
assert0@xfail("hasattr(os,'sep')")deftest_hello3():
assert0@xfail(reason="bug 110")deftest_hello4():
assert0@xfail('pytest.__version__[0] != "17"')deftest_hello5():
assert0deftest_hello6():
pytest.xfail("reason")
@xfail(raises=IndexError)deftest_hello7():
x = []
x[1] = 1
使用report-on-xfail选项运行它会提供以下输出:
Copyexample $ 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等标记应用于各个测试实例如:
Copyimport 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")
),
],
)deftest_increment(n,expected):
assert n + 1 == expected
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
如果对你有帮助的话,点个赞收个藏,给作者一个鼓励。也方便你下次能够快速查找。
如有不懂还要咨询下方小卡片,博主也希望和志同道合的测试人员一起学习进步
在适当的年龄,选择适当的岗位,尽量去发挥好自己的优势。
我的自动化测试开发之路,一路走来都离不每个阶段的计划,因为自己喜欢规划和总结,
测试开发视频教程、学习笔记领取传送门!!!