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---------------------------")
重新運行用例,得到結果如下: