前言
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 後置操做")
運行結果