pytest文檔33-Hooks函數獲取用例執行結果(pytest_runtest_makereport)

前言

pytest提供的不少鉤子(Hooks)方法方便咱們對測試用例框架進行二次開發,能夠根據本身的需求進行改造。
先學習下pytest_runtest_makereport這個鉤子方法,能夠更清晰的瞭解用例的執行過程,並獲取到每一個用例的執行結果。
html

pytest_runtest_makereport

先看下相關的源碼,在_pytest/runner.py下,能夠導入以後,點進去查看node

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是測試步驟,具體執行過程以下:session

  • 先執行when='setup' 返回setup 的執行結果
  • 而後執行when='call' 返回call 的執行結果
  • 最後執行when='teardown'返回teardown 的執行結果

運行案例

conftest.py 寫 pytest_runtest_makereport 內容,打印運行過程和運行結果app

# 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("上海-悠悠")

運行結果以下學習

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
上海-悠悠
------------------------------------
用例執行結果 <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 ===========================

從運行結果能夠看出,運行用例的過程會經歷三個階段:setup-call-teardown,每一個階段都會返回的 Result 對象和 TestReport 對象,以及對象屬性。
setup和teardown上面的用例默認都沒有,結果都是passed。
測試

setup和teardown

給用例寫個fixture增長用例的前置和後置操做,conftest.py內容以下spa

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 後置操做")

運行結果以下3d

setup失敗狀況

當setup執行失敗了,setup的執行結果的failed,後面的call用例和teardown都不會執行了code

此時用例的狀態是:error, 也就是用例(call)都還沒開始執行,就異常了。

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("上海-悠悠")
    assert 1==0

那麼此時運行的結果就是failed

teardown失敗了

若是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("上海-悠悠")

最終統計的結果: 1 passed, 1 error in 0.16 seconds

只獲取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 後置操做")

運行結果

相關文章
相關標籤/搜索