2、pytest中文文档--使用和调用
- 1. 通过python -m pytest调用pytest
- 2. pytest执行结束时返回的状态码
- 3. 获取帮助信息
- 4. 最多允许失败的测试用例数
- 5. 执行指定的测试用例
- 6. 修改回溯信息的输出模式
- 7. 总结报告
- 8. 失败时加载PDB(Python Debugger)环境
- 9. 开始执行时就加载PDB环境
- 10. 设置断点
- 11. 使用内置的中断函数
- 12. 分析测试执行时间
- 13. 错误句柄
- 14. 创建JUnitXML格式的测试报告
- 15. 在报告中为测试用例附加额外的子节点信息
- 16. 创建纯文本格式的测试报告
- 17. 为测试报告提供URL链接 -- pastebin服务
- 18. 尽早的加载插件
- 19. 去使能插件
- 20. 在python代码中调用pytest
1. 通过python -m pytest
调用pytest
你可以通过python的解释器来执行测试:
python -m pytest [...]
但是,这和直接执行pytest [...]
命令的效果几乎是一模一样的;
2. pytest
执行结束时返回的状态码
pytest
命令执行结束,可能会返回以下六种状态码:
- 0:(OK)所有收集到的用例测试通过
- 1:(TESTS_FAILED)有用例测试失败
- 2:(INTERRUPTED)用户打断测试执行
- 3:(INTERNAL_ERROR)测试执行的过程中,发生内部错误
- 4:(USAGE_ERROR)
pytest
命令使用错误 - 5:(NO_TESTS_COLLECTED)没有收集到测试用例
它们在枚举类 _pytest.main.ExitCode 中声明。并且,其作为公开API的一部分,能够直接引入和访问:
from pytest import ExitCode
3. 获取帮助信息
pytest --version # 查看版本号和pytest的引入路径
pytest -h # 查看帮助信息
4. 最多允许失败的测试用例数
当达到最大上限时,退出执行;如未配置,则没有上限:
pytest -x # 遇到第一个失败时,退出执行
pytest --maxfail==2 # 遇到第二个失败时,退出执行
5. 执行指定的测试用例
pytest
支持多种方式来执行特定的测试用例:
5.1. 执行指定模块中的测试用例
pytest test_mod.py
5.2. 执行指定目录下所有的测试用例
pytest testing/
5.3. 执行文件名、类名或者函数名中包含特定关键字的测试用例
执行当前目录下,名字包含_class
但不包含two
的测试用例:
pytest -k "_class and not two" .
注意:python的关键字不可以应用在
-k
选项中,例如,class
、def
等。
5.4. 执行指定nodeid
的测试用例
pytest
为每一个收集到的测试用例指定一个唯一的nodeid
。其由模块名加说明符构成,中间以::
间隔。
其中,说明符可以是类名、函数名以及由parametrize
标记赋予的参数:
# src/chapter-2/test_nodeid.py
import pytest
def test_one():
print('test_one')
assert 1
class TestNodeId:
def test_one(self):
print('TestNodeId::test_one')
assert 1
@pytest.mark.parametrize('x,y', [(1, 1), (3, 4)])
def test_two(self, x, y):
print(f'TestNodeId::test_two::{x} == {y}')
assert x == y
在上述示例中,我们创建了三个测试用例,分别对应不同的说明符:
指定函数名执行
$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::test_one
test_one
.
1 passed in 0.01s
指定类名+函数名执行
$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::TestNodeId::test_one
TestNodeId::test_one
.
1 passed in 0.01s
指定由
parametrize
标记赋予的参数执行$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::TestNodeId::test_two[1-1]
TestNodeId::test_two::1 == 1
.
1 passed in 0.01s
这里对参数
x
、y
赋值的形式是[1-1]
,中间以-
间隔;单个或多个参数的赋值形式以此类比;并且,只能为
[1-1]
或者[3-4]
,其它的会报错;
注意:
这里我们也可以使用
-k
选项达到同样的效果:
首先,可以使用
--collect-only
选项查看用例名:λ pipenv run pytest -q -s --collect-only src/chapter-2/test_nodeid.py
test_nodeid.py::test_one
test_nodeid.py::TestNodeId::test_one
test_nodeid.py::TestNodeId::test_two[1-1]
test_nodeid.py::TestNodeId::test_two[3-4]
然后,使用
-k
执行符合规则的用例,例如:执行test_nodeid.py::test_one
:λ pipenv run pytest -q -s -k 'test_one and not TestNodeId' src/chapter-2/test_nodeid.py
test_one
.
1 passed, 3 deselected in 0.02s
结果和执行
pipenv run pytest -q -s src/chapter-2/test_nodeid.py::test_one
一样;
5.5. 执行指定标记的用例
pytest -m slow
5.6. 执行指定包中的测试用例
pytest --pyargs pkg.testing
pytest
会引入pkg.testing
包,并在它的系统目录下搜寻测试用例并执行;
6. 修改回溯信息的输出模式
pytest回溯信息的输出一共有六种模式:auto/long/short/line/native/no,用--tb
选项指定:
pytest -l, --showlocals # 打印本地变量
pytest --tb=auto # 默认模式
pytest --tb=long # 尽可能详细的输出
pytest --tb=short # 更简短的输出
pytest --tb=line # 每个失败信息总结在一行中
pytest --tb=native # python的标准输出
pytest --tb=no # 不打印失败信息
--full-trace
是一种比--tb=long
更详细的输出模式。它甚至能观察到用户打断执行(Ctrl+C
)时的回溯信息,而上述六种模式默认是不输出此类信息的。
7. 总结报告
-r
选项可以在执行结束后,打印一个简短的总结报告。在执行的测试用例很多时,可以让你对结果有个清晰的了解:
# src/chapter-2/test_report.py
import pytest
@pytest.fixture
def error_fixture():
assert 0
def test_ok():
print("ok")
def test_fail():
assert 0
def test_error(error_fixture):
pass
def test_skip():
pytest.skip("skipping this test")
def test_xfail():
pytest.xfail("xfailing this test")
@pytest.mark.xfail(reason="always xfail")
def test_xpass():
pass
$ pipenv run pytest -q -rA src/chapter-2/test_report.py
.FEsxX [100%]
================================ ERRORS =================================
_____________________ ERROR at setup of test_error ______________________
@pytest.fixture
def error_fixture():
> assert 0
E assert 0
src/chapter-2/test_report.py:27: AssertionError
=============================== FAILURES ================================
_______________________________ test_fail _______________________________
def test_fail():
> assert 0
E assert 0
src/chapter-2/test_report.py:35: AssertionError
================================ PASSES =================================
________________________________ test_ok ________________________________
------------------------- Captured stdout call --------------------------
ok
======================== short test summary info ========================
PASSED src/chapter-2/test_report.py::test_ok
SKIPPED [1] /Users/yaomeng/Private/Projects/pytest-chinese-doc/src/chapter-2/test_report.py:44: skipping this test
XFAIL src/chapter-2/test_report.py::test_xfail
reason: xfailing this test
XPASS src/chapter-2/test_report.py::test_xpass always xfail
ERROR src/chapter-2/test_report.py::test_error - assert 0
FAILED src/chapter-2/test_report.py::test_fail - assert 0
1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.08s
-r
选项后面要紧接这一个参数,用于过滤显示测试用例的结果。
以下是所有有效的字符参数:
- f:失败的
- E:出错的
- s:跳过执行的
- x:跳过执行,并标记为xfailed的
- X:跳过执行,并标记为xpassed的
- p:测试通过的
- P:测试通过,并且有输出信息的;即用例中有
print
等 - a:除了测试通过的,其他所有的;即除了
p
和P
的 - A:所有的
上述字符参数可以叠加使用,例如:我们期望过滤出失败的和未执行的:
pytest -rfs
8. 失败时加载PDB(Python Debugger)环境
PDB
是python
内建的诊断器,pytest
允许通过以下命令在执行失败时进入这个诊断器模式:
pytest --pdb
pytest
会在测试用例失败(或者Ctrl+C
)时,调用这个诊断器:
# src/chapter-2/test_pdb.py
def test_fail():
x = 1
assert x == 0
$ pipenv run pytest -q --pdb src/chapter-2/test_pdb.py
F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
def test_fail():
x = 1
> assert x == 0
E assert 1 == 0
src/chapter-2/test_pdb.py:25: AssertionError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> PDB post_mortem (IO-capturing turned off) >>>>>>>>>>>>>>>
> /Users/yaomeng/Private/Projects/pytest-chinese-doc/src/chapter-2/test_pdb.py(25)test_fail()
-> assert x == 0
(Pdb)
(Pdb) x
1
(Pdb)
(Pdb) import sys
(Pdb) sys.last_value
AssertionError('assert 1 == 0')
(Pdb) sys.last_type
<class 'AssertionError'>
(Pdb) sys.last_traceback
<traceback object at 0x1077ec808>
你还可以访问测试用例的本地变量x
;
失败的信息存储在sys.last_value, sys.last_type, sys.last_traceback
变量中,你可以在交互环境中访问它们;
使用exit
命令,退出PDB
环境;
9. 开始执行时就加载PDB
环境
通过以下命令,pytest
允许你在每个测试用例开始执行时,就加载PDB
环境:
pytest --trace
10. 设置断点
在测试用例代码中添加import pdb;pdb.set_trace()
,当其被调用时,pytest
会停止这条用例的输出:
- 其他用例不受影响;
- 通过
continue
命令,退出PDB
环境,并继续执行用例;
11. 使用内置的中断函数
python 3.7介绍了一个内置breakpoint()
函数。pytest可以在以下场景中支持使用:
- 当
breakpoint()
被调用,并且PYTHONBREAKPOINT
为None
时,pytest
会使用内部自定义的PDB
代替系统的; - 测试执行结束时,自动切回系统自带的
PDB
; - 当加上
--pdb
选项时,breakpoint()
和测试发生错误时,都会调用内部自定义的PDB
; --pdbcls
选项允许指定一个用户自定义的PDB
类;
12. 分析测试执行时间
获取执行最慢的10个测试用例:
pytest --durations=10
默认情况下,pytest
不会显示执行时间<0.01s的测试用例,可以使用-vv
选项查看它们;
13. 错误句柄
5.0版本新增特性
在测试执行中发生段错误或者超时的情况下,faulthandler
标准模块可以转储python
的回溯信息;
它在pytest
的执行中默认使能,使用-p no:faulthandler
选项可以关闭它;
同样,faulthandler_timeout=X
配置项,可用于当测试用例的完成时间超过X
秒时,转储所有线程的python
回溯信息:
# src/chapter-2/pytest.ini
[pytest]
faulthandler_timeout=5
配置测试执行的超时时间是5秒;
# test_fault_handler.py
import time
def test_faulthandler():
time.sleep(7)
assert 1
测试用例中添加等待7秒的操作;
默认使能
faulthandler
的情况:$ pipenv run pytest -q src/chapter-2/test_faulthandler.py
Timeout (0:00:05)!
Thread 0x000000010ff275c0 (most recent call first):
File "/Users/yaomeng/Private/Projects/pytest-chinese-doc/src/chapter-2/test_faulthandler.py", line 26 in test_faulthandler
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/python.py", line 170 in pytest_pyfunc_call
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda>
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/python.py", line 1423 in runtest
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 117 in pytest_runtest_call
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda>
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 192 in <lambda>
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 220 in from_call
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 192 in call_runtest_hook
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 167 in call_and_report
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 87 in runtestprotocol
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/runner.py", line 72 in pytest_runtest_protocol
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda>
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 256 in pytest_runtestloop
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda>
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 235 in _main
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 191 in wrap_session
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/main.py", line 228 in pytest_cmdline_main
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/callers.py", line 187 in _multicall
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 86 in <lambda>
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/manager.py", line 92 in _hookexec
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/pluggy/hooks.py", line 286 in __call__
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/lib/python3.7/site-packages/_pytest/config/__init__.py", line 77 in main
File "/Users/yaomeng/.local/share/virtualenvs/pytest-chinese-doc-EK3zIUmM/bin/pytest", line 10 in <module>
. [100%]
1 passed in 7.02s
在执行刚超过5秒的时候会打印出回溯信息。但不会中断测试的执行;
去使能
faulthandler
的情况:$ pipenv run pytest -q -p no:faulthandler src/chapter-2/test_faulthandler.py
. [100%]
1 passed in 7.02s
超时并不会触发回溯信息的打印;
注意:
这个功能是从pytest-faulthandler插件合并而来的,但是有两点不同:
- 去使能时,使用
-p no:faulthandler
代替原来的--no-faulthandler
;- 使用
faulthandler_timeout
配置项代替--faulthandler-timeout
命令行选项来配置超时时间。当然,你也可以使用-o faulthandler_timeout=X
在命令行配置;
14. 创建JUnitXML
格式的测试报告
使用如下命令,可以在指定的path
中创建一个能被Jenkins或者其他CI工具读取的XML
格式的测试报告:
pytest --junitxml=path
你可以在项目的pytest.ini
文件中,通过设置junit_suite_name
的值,自定义XML
文件中testsuite
根节点的name
信息:
junit_suite_name
是4.0版本新增的配置项;
# src/chapter-2/pytest.ini
[pytest]
junit_suite_name = pytest_chinese_doc
我们来执行一个测试用例test_nodeid.py::test_one
看看效果:
pipenv run pytest -q --junitxml=src/chapter-2/report/test_one.xml src/chapter-2/test_nodeid.py::test_one
生成的XML
测试报告:
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1"
time="0.030" timestamp="2019-09-27T14:33:32.459788">
<testcase classname="test_nodeid" file="test_nodeid.py" line="24" name="test_one" time="0.002">
<system-out>test_one
</system-out>
</testcase>
</testsuite>
</testsuites>
我们可以看到,<testsuite>
节点的name
属性的值,变为我们所期望的pytest_chinese_doc
,而不是默认的pytest
;
JUnit XML规定time
属性应该表明测试用例执行的全部耗时,包含setup
和teardown
中的操作,这也是pytest的默认行为;
如果你只想记录测试用例执行的时间,只需要做如下配置:
# src/chapter-2/pytest.ini
junit_duration_report = call
15. 在报告中为测试用例附加额外的子节点信息
我们有两种方式实现这个功能:
使用
record_property fixture
:为
test_record_property
用例添加一个额外的test_id
:# src/chapter-2/test_xml_report.py def test_record_property(record_property):
record_property("test_id", 10010)
assert 1
在报告中的表现为
<property name="test_id" value="10010" />
:<!-- src/chapter-2/report/test_record_property.xml --> <?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1"
time="0.024" timestamp="2019-09-27T15:02:41.277369">
<testcase classname="test_xml_report" file="test_xml_report.py" line="22" name="test_record_property" time="0.002">
<properties>
<property name="test_id" value="10010" />
</properties>
</testcase>
</testsuite>
</testsuites>
解析一个自定义的标记
@pytest.mark.test_id()
:首先,修改
pytest_collection_modifyitems
钩子方法,添加对test_id
标记的支持:# src/chapter-2/conftest.py def pytest_collection_modifyitems(session, config, items):
for item in items:
for marker in item.iter_markers(name="test_id"):
test_id = marker.args[0]
item.user_properties.append(("test_id", test_id))
然后,修改测试用例:
# src/chapter-2/test_xml_report.py import pytest @pytest.mark.test_id(10010)
def test_record_property1():
assert 1
在报告中的也表现为
<property name="test_id" value="10010" />
:<!-- src/chapter-2/report/test_record_property1.xml --> <?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1"
time="0.029" timestamp="2019-09-27T15:16:05.309308">
<testcase classname="test_xml_report" file="test_xml_report.py" line="29" name="test_record_property1" time="0.001">
<properties>
<property name="test_id" value="10010" />
</properties>
</testcase>
</testsuite>
</testsuites>
注意:
这是我们会接收到一个告警:
PytestUnknownMarkWarning: Unknown pytest.mark.test_id - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
这是因为我们没有在
pytest
中注册test_id
标记,但不影响正常的执行;如果你想去除这个告警,只需要在
pytest.ini
的配置文件中注册这个标记:[pytest]
markers =
test_id: 为测试用例添加ID
注意:
变动后的报告可能不符合最新的
JUnitXML
的模式检查规则,导致在某些CI工具上可能会发生未知的错误;
15.1. 在报告中为测试用例附加额外的属性信息
可以通过record_xml_attribute fixture
为测试用例附加额外的属性,而不像record_property
为其添加子节点;
为测试用例添加一个test_id
属性,并修改原先的classname
属性:
# src/chapter-2/test_xml_report.py
def test_record_property2(record_xml_attribute):
record_xml_attribute('test_id', 10010)
record_xml_attribute('classname', 'custom_classname')
assert 1
在报告中的表现为<testcase classname="custom_classname" test_id="10010" ...
:
<!-- src/chapter-2/report/test_record_property2.xml -->
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1"
time="0.028" timestamp="2019-09-27T15:35:47.093494">
<testcase classname="custom_classname" file="test_xml_report.py" line="34" name="test_record_property2"
test_id="10010" time="0.001"></testcase>
</testsuite>
</testsuites>
注意:
record_xml_attribute
目前是一个实验性的功能,未来可能被更强大的API所替代,但功能本身会被保留。变动后的报告可能不符合最新的
JUnitXML
的模式检查规则,导致在某些CI工具上可能会发生未知的错误;
15.2. 在报告中为测试集附加额外的子节点信息
4.5版本新增功能
可以通过自定义一个session
作用域级别的fixture
,为测试集添加子节点信息,并且会作用于所有的测试用例;
这个自定义的fixture
需要调用另外一个record_testsuite_property fixture
:
record_testsuite_property
接收两个参数name
和value
以构成<property>
标签,其中,name
必须为字符串,value
会转换为字符串并进行XML转义;
# src/chapter-2/test_xml_report.py
@pytest.fixture(scope="session")
def log_global_env_facts(record_testsuite_property):
record_testsuite_property("EXECUTOR", "luizyao")
record_testsuite_property("LOCATION", "NJ")
def test_record_property3(log_global_env_facts):
assert 1
生成的测试报告表现为:在testsuite
节点中,多了一个properties
子节点,包含所有新增的属性节点,而且,它和所有的testcase
节点是平级的;
<!-- src/chapter-2/report/test_record_property3.xml -->
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite errors="0" failures="0" hostname="NJ-LUYAO-T460" name="pytest_chinese_doc" skipped="0" tests="1"
time="0.027" timestamp="2019-09-27T15:52:34.562238">
<properties>
<property name="EXECUTOR" value="luizyao" />
<property name="LOCATION" value="NJ" />
</properties>
<testcase classname="test_xml_report" file="test_xml_report.py" line="46" name="test_record_property3" time="0.002">
</testcase>
</testsuite>
</testsuites>
注意:
这样生成的XML文件是符合最新的
xunit
标准的,这点和record_property
、record_xml_attribute
正好相反;
16. 创建纯文本格式的测试报告
不推荐使用,计划在
pytest 6.0
中删除这个功能
使用如下命令,可以在指定的path
中创建一个纯文本的测试报告:
pytest --resultlog=path
17. 为测试报告提供URL
链接 -- pastebin
服务
目前,只实现了在http://bpaste.net上的展示功能;
为每一个失败的测试用例创建一个URL
pytest --pastebin=failed
也可以通过添加
-x
选项,只为第一个失败的测试用例创建一个URL;为所有的测试用例创建一个URL
pytest --pastebin=all
18. 尽早的加载插件
你可以在命令行中使用-p
选项,来尽早的加载某一个插件:
pytest -p mypluginmodule
-p
选项接收一个name
参数,这个参数可以为:
- 一个完整的本地插件引入,例如:
myproject.plugins
,其必须是可以import
的。 - 一个公共插件的名称,这是其注册时在
setuptools
中赋予的名字,例如:尽早的加载pytest-cov插件:pytest -p pytest_cov
19. 去使能插件
你可以在命令行中使用-p
结合no:
,来去使能一个插件的加载,例如:
pytest -p no:doctest
20. 在python
代码中调用pytest
可以直接在代码中调用pytest
:
pytest.main()
这和你在命令行中执行pytest .
几乎是一样的,但其也有以下特点:
不会触发
SystemExit
,而是返回exitcode:# src/chapter-2/invoke_via_main.py import time def test_one():
time.sleep(10) if __name__ == '__main__':
import pytest
ret = pytest.main(['-q', __file__])
print("pytest.main() 返回 pytest.ExitCode.INTERRUPTED:", ret == pytest.ExitCode.INTERRUPTED)
用例中有等待10秒的操作,在这期间,打断执行(
Ctr+C
),pytest.main()
返回的是INTERRUPTED
状态码;λ pipenv run python src/chapter-2/invoke_via_main.py !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
D:\Personal Files\Projects\pytest-chinese-doc\src\chapter-2\invoke_via_main.py:26: KeyboardInterrupt
(to show a full traceback on KeyboardInterrupt use --full-trace)
no tests ran in 1.04s
pytest.main() 返回 pytest.ExitCode.INTERRUPTED: True Aborted!
传递选项和参数:
pytest.main(["-x", "mytestdir"])
指定一个插件:
import pytest class MyPlugin:
def pytest_sessionfinish(self):
print("*** test run reporting finishing") pytest.main(["-qq"], plugins=[MyPlugin()])
注意:
调用
pytest.main()
会引入你的测试文件以及其引用的所有模块。由于python引入机制的缓存特性,当这些文件发生变化时,后续再调用pytest.main()
(在同一个程序执行过程中)时,并不会响应这些文件的变化。基于这个原因,我们不推荐在同一个程序中多次调用
pytest.main()
(例如:为了重新执行测试;如果你确实有这个需求,或许可以考虑pytest-repeat插件);
2、pytest中文文档--使用和调用的更多相关文章
- 4、pytest 中文文档--pytest-fixtures:明确的、模块化的和可扩展的
目录 1. fixture:作为形参使用 2. fixture:一个典型的依赖注入的实践 3. conftest.py:共享fixture实例 4. 共享测试数据 5. 作用域:在跨类的.模块的或整个 ...
- pytest -- 中文文档
pytest-chinese-doc pytest官方文档(5.1.3版本)的中文翻译,但不仅仅是简单的翻译: 更多的例子,尽量做到每一知识点都有例子: 更多的拓展阅读,部分章节添加了作者学习时,所查 ...
- 3、pytest中文文档--编写断言
目录 编写断言 使用assert编写断言 编写触发期望异常的断言 特殊数据结构比较时的优化 为失败断言添加自定义的说明 关于断言自省的细节 复写缓存文件 去使能断言自省 编写断言 使用assert编写 ...
- 1、pytest中文文档--安装和入门
目录 安装和入门 安装pytest 创建你的第一个测试用例 执行多个测试用例 检查代码是否触发一个指定的异常 在一个类中组织多个测试用例 申请一个唯一的临时目录用于功能测试 安装和入门 Python版 ...
- java冒泡排序-选择排序-插入排序-使用API中文文档直接调用函数
import java.util.Arrays; public class ArrayDemo2_3 { public static void main(String []args) { //---- ...
- Phoenix综述(史上最全Phoenix中文文档)
个人主页:http://www.linbingdong.com 简书地址:http://www.jianshu.com/users/6cb45a00b49c/latest_articles 网上关于P ...
- Spring中文文档
前一段时间翻译了Jetty的一部分文档,感觉对阅读英文没有大的提高(*^-^*),毕竟Jetty的受众面还是比较小的,而且翻译过程中发现Jetty的文档写的不是很好,所以呢翻译的兴趣慢慢就不大了,只能 ...
- jQuery 3.1 API中文文档
jQuery 3.1 API中文文档 一.核心 1.1 核心函数 jQuery([selector,[context]]) 接收一个包含 CSS 选择器的字符串,然后用这个字符串去匹配一组元素. jQ ...
- jQuery EasyUI API 中文文档 - ValidateBox验证框
jQuery EasyUI API 中文文档 - ValidateBox验证框,使用jQuery EasyUI的朋友可以参考下. 用 $.fn.validatebox.defaults 重写了 d ...
随机推荐
- 最全数据分析资料汇总(含python、爬虫、数据库、大数据、tableau、统计学等)
一.Python基础 Python简明教程(Python3) Python3.7.4官方中文文档 Python标准库中文版 廖雪峰 Python 3 中文教程 Python 3.3 官方教程中文版 P ...
- 夯实Java基础(六)——包装类
1.包装类简介 我们都知道Java是面向对象编程语言,包含了8种基本数据类型,但是这8种基本数据类型并不支持面向对象的特征,它们既不是类,也不能调用方法.这在实际使用时存在很多的不便,比如int类型需 ...
- python基础之循环与迭代器
循环 python 循环语句有for循环和while循环. while循环while循环语法 while 判断条件: 语句 #while循环示例 i = 0 while i < 10: i += ...
- Java中的时间二三事
实习过程中对于时间的处理有很多,有的还涉及到从数据库取出时间,所以做一些总结,想到那先写到哪,慢慢补充. 首先最常见的是java.util中的Date类,这个类封装了当前的日期和时间,它实际是计 ...
- xtuils
xutils的使用必须导入一个依赖 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceS ...
- 面试java后端面经_1
1 自我介绍(建议提前准备:没准备的可以这样说:来自某学校 姓名 专业 学的啥 为啥学 自己陆陆续续开发的项目 毕业将近 找工作 在哪看到贵公司的招聘 准备了啥 大概这样) 例子:您好!我是来自XXX ...
- Javascript十大排序算法的实现方法
上一篇中,实现了Javascript中的冒泡排序方法,下面把剩余的九种排序算法实现 选择排序: var array = []; for(var i=0;i<100000;i++){ var x ...
- Javasrcipt中从一个url或者从一个字符串中获取参数值得方法
从url中获取参数值是che程序开发过程中的常用需求,偶然得闲,便抽空研究了一下javasrcipt下,获取参数的办法(JAVA中也类似). 首先看url的规范: URL组成:protocol :// ...
- 微信小程序商城系统怎样搭建?
微信是一种非常便捷的生活方式,微信小程序一直深受企业和商家的青睐,如美团.京东.拼多多.唯品会.小红书等知名公司都推出了自己的小程序.对于网上商城小程序的开发似乎是一件非常难的事情,用什么开发?如何开 ...
- 如何使用Python连接ldap
如何使用Python连接ldap 好多使用ldap认证的软件都是Python的,比如superset和airflow, 好吧,他们都是airbnb家的.在配置ldap的时候可能会出现认证失败,你不知道 ...