1. 程式人生 > 其它 >Pytest學習-通過hooks函式(pytest_runtest_makereport)獲取用例結果

Pytest學習-通過hooks函式(pytest_runtest_makereport)獲取用例結果

Pytest中提供了很多鉤子函式,可以方便我們基於此進行二次開發,另外通過對Pytest鉤子函式的學習,我們也能夠更好的理解到其在用例執行的各階段到底做了哪些工作。

今天我們將學習Pytest中的鉤子函式:pytest_runtest_makereport,它可以讓我們獲取到用例執行結果。

鉤子函式的使用

我們可以在Pytest原始碼中的 runner.py 檔案下找到 pytest_runtest_makereport() 鉤子函式,大致如下:

def pytest_runtest_makereport(item, call):
    return TestReport.from_item_and_call(item, call)

該函式操作時傳入 測試用例 item 和 測試步驟 call,返回的資料是測試用例的執行結果。下面是簡單的示例:

# test_01.py
import pytest


def test_01():
    """用例描述:XXXXXX"""
    print("測試一下")
    assert 1
# conftest.py
import pytest


@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
    print("------------------------Start---------------------------")
    out = yield
    res = out.get_result()
    print("執行結果:{}".format(res))
    print("測試用例:{}".format(item))
    print("測試步驟:{}".format(call))
    print("------------------------End---------------------------")

把上面的用例執行後,得到如下結果:

從上方輸出的資訊可以知道,我們在 Pytest 中執行一條用例的時候,需要經過以下3個階段:

  • 最先執行 when='setup' 的前置操作
  • 接著執行 when='call' 的用例部分
  • 最後執行 when='teardown' 的後置操作

上面的每一個階段,都會返回相應的執行結果,如果用例中不存在前置/後置操作,那麼該階段預設 outcome='passed'

當然對於這3個階段,也都可能會出現失敗的情況。為了更方便模擬操作失敗的情況,我們在 conftest.py 中使用 fixture 增加一個函式,然後設定為自動呼叫。

@pytest.fixture(scope="function", autouse=True)
def setup_teardown():
    print("------------------------這是setup前置操作---------------------------")
    yield
    print("------------------------這是teardown後置操作---------------------------")

setup前置操作失敗

為了讓用例在前置操作中出現失敗,我們可以簡單修改下 conftest.py 程式碼:

@pytest.fixture(scope="function", autouse=True)
def setup_teardown():
    assert 0
    print("------------------------這是setup前置操作---------------------------")
    yield
    print("------------------------這是teardown後置操作---------------------------")

然後重新執行用例,得到結果如下:

從用例結果中可以看到,我們在 Pytest 中執行用例時,如果在setup前置操作中就出現失敗,那麼其不會再呼叫測試用例和執行後置操作(上面 teardown 的資訊也沒有打印出來),而用例的執行結果為:error

call測試用例失敗

為了讓用例在 call 呼叫中出現失敗,我們可以簡單修改下 test_01.py 程式碼:

import pytest


def test_01():
    """用例描述:XXXXXX"""
    print("斷言失敗")
    assert 0

重新執行用例,得到結果如下:

從用例結果中可以看到,我們在 Pytest 中執行用例時,setup前置操作成功,但在call測試用例中出現失敗,那麼其會繼續執行後置操作,最後用例的執行結果為:failed

teardown後置操作失敗

為了讓用例在前置操作中出現失敗,我們可以簡單修改下 conftest.py 程式碼:

@pytest.fixture(scope="function", autouse=True)
def setup_teardown():
    print("------------------------這是setup前置操作---------------------------")
    yield
    print("------------------------這是teardown前置操作---------------------------")
    assert 0

重新執行用例,得到結果如下:

從用例結果中可以看到,我們在 Pytest 中執行用例時,teardown後置操作失敗,那麼最後用例的結果為:1 passed, 1 error

獲取用例執行時的資訊

有時候,我們想要獲取測試用例執行的詳細資訊,比如列印用例描述,或在用例執行失敗後列印日誌等資訊,那麼我們可以優化下程式碼:

@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
    print("------------------------Start---------------------------")
    out = yield  # 鉤子函式的呼叫結果
    res = out.get_result()  # 獲取用例執行結果
    print("執行結果:{}".format(res))
    if res.when == "call" and res.outcome == "failed":  # 只獲取call用例失敗時的資訊
        print("測試用例:{}".format(item))
        print("用例描述:{}".format(item.function.__doc__))
        print("測試步驟:{}".format(call))
        print("用例失敗異常資訊:{}".format(call.excinfo))
        print("用例失敗時的詳細日誌:{}".format(res.longrepr))
    print("------------------------End---------------------------")

重新執行用例,得到結果如下: