Time will tell.
Pytest 提供了很多钩子方法让我们对测试用例框架进行二次开发,可根据自己的需求进行改造。所以接下来就来学习下pytest_runtest_makereport 这个钩子方法,更清晰地了解用例的执行过程,并获取每个用例的执行结果。
?
pytest_runtest_makereport
来看下相关源码:
from _pytest import runner
# 对应源码
def pytest_runtest_makereport(item, call):
""" return a :py:class:`_pytest.runner.TestReport` object
for the given :py:class:`pytest.Item` and
:py:class:`_pytest.runner.CallInfo`.
"""
这里item 是测试用例,call 是测试步骤,具体过程如下:
- 先执行 when=’setup’ 返回
setup 的执行结果。 - 然后执行 when=’call’ 返回
call 的执行结果。 - 最后执行 when=’teardown’ 返回
teardown 的执行结果。
1、案例
conftest.py 写pytest_runtest_makereport 内容,打印运行过程和运行结果。
# conftest.py
import pytest
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
print('------------------------------------')
# 获取钩子方法的调用结果
out = yield
print('用例执行结果', out)
# 3\. 从钩子方法的调用结果中获取测试报告
report = out.get_result()
print('测试报告:%s' % report)
print('步骤:%s' % report.when)
print('nodeid:%s' % report.nodeid)
print('description:%s' % str(item.function.__doc__))
print(('运行结果: %s' % report.outcome))
test_a.py 写一个简单的用例:
def test_a():
'''用例描述:test_a'''
print("123")
运行结果:
D:\soft\code\pytest_jenkins_demo\demo>pytest -s
============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-4.5.0, py-1.5.4, pluggy-0.13.1
rootdir: D:\demo
plugins: html-1.19.0,
collected 1 item
test_a.py ------------------------------------
用例执行结果 <pluggy.callers._Result object at 0x0000027C547332B0>
测试报告:<TestReport 'test_a.py::test_a' when='setup' outcome='passed'>
步骤:setup
nodeid:test_a.py::test_a
description:用例描述:test_a
运行结果: passed
123
------------------------------------
用例执行结果 <pluggy.callers._Result object at 0x0000027C547332B0>
测试报告:<TestReport 'test_a.py::test_a' when='call' outcome='passed'>
步骤:call
nodeid:test_a.py::test_a
description:用例描述:test_a
运行结果: passed
.------------------------------------
用例执行结果 <pluggy.callers._Result object at 0x0000027C54750A20>
测试报告:<TestReport 'test_a.py::test_a' when='teardown' outcome='passed'>
步骤:teardown
nodeid:test_a.py::test_a
description:用例描述:test_a
运行结果: passed
========================== 1 passed in 0.06 seconds ===========================
从结果可以看到,用例的过程会经历3个阶段:
setup -> call -> teardown
每个阶段会返回Result 对象和TestReport 对象,以及对象属性。setup 和teardown 上面的用例默认没有,结果都是passed 。
2、setup和teardown
给用例写个fixture 增加用例的前置和后置操作,conftest.py 如下:
import pytest
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
print('------------------------------------')
# 获取钩子方法的调用结果
out = yield
print('用例执行结果', out)
# 3\. 从钩子方法的调用结果中获取测试报告
report = out.get_result()
print('测试报告:%s' % report)
print('步骤:%s' % report.when)
print('nodeid:%s' % report.nodeid)
print('description:%s' % str(item.function.__doc__))
print(('运行结果: %s' % report.outcome))
@pytest.fixture(scope="session", autouse=True)
def fix_a():
print("setup 前置操作")
yield
print("teardown 后置操作")
运行结果:
?
当setup 执行失败了,setup 执行结果的failed ,后面的call 用例和teardown 都不会执行。
?
此时用例的状态是error ,也就是用例call 还没开始执行就异常了。
如果setup 正常执行,但测试用例call 失败了。
@pytest.fixture(scope="session", autouse=True)
def fix_a():
print("setup 前置操作")
yield
print("teardown 后置操作")
test_a.py 用例:
def test_a():
'''用例描述:test_a'''
print("123")
assert 1==0
?
那么此时运行结果就是failed 。
如果setup 正常执行,测试用例call 正常执行,teardown 失败了:
@pytest.fixture(scope="session", autouse=True)
def fix_a():
print("setup 前置操作")
yield
print("teardown 后置操作")
raise Exception("teardown 失败了")
teat_a.py 用例:
def test_a():
'''用例描述:test_a'''
print("123")
?
最终结果:1 passed, 1 error in 0.16 seconds 。
3、只获取call结果
我们在写用例时,如果保证setup 和teardown 不报错,只关注用例的运行结果,前面的pytest_runtest_makereport 钩子方法执行了三次。可以加个判断:if report.when == “call” 。
import pytest
from _pytest import runner
'''
# 对应源码
def pytest_runtest_makereport(item, call):
""" return a :py:class:`_pytest.runner.TestReport` object
for the given :py:class:`pytest.Item` and
:py:class:`_pytest.runner.CallInfo`.
"""
'''
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
print('------------------------------------')
# 获取钩子方法的调用结果
out = yield
# print('用例执行结果', out)
# 3\. 从钩子方法的调用结果中获取测试报告
report = out.get_result()
if report.when == "call":
print('测试报告:%s' % report)
print('步骤:%s' % report.when)
print('nodeid:%s' % report.nodeid)
print('description:%s' % str(item.function.__doc__))
print(('运行结果: %s' % report.outcome))
@pytest.fixture(scope="session", autouse=True)
def fix_a():
print("setup 前置操作")
yield
print("teardown 后置操作")
以上就是全部内容了,如果你对自动化软件测试、面试题感兴趣可以加入我们扣裙一起学习http://点击链接加入群聊【软件测试大本营】:https://jq.qq.com/?_wv=1027&k=EYMeZFZy。会有各项测试学习资源发放,更有行业深潜多年的技术人分析讲解。
最后愿你能成为一名优秀的测试工程师!
欢迎【点赞】、【评论】、【关注】~
Time will tell.(时间会说明一切)
|