allure鈎子函數 && selenium 截圖的四種方式 && allure集成錯誤截圖報告


1.selenium 截圖的四種方式

1. save_sreenshoot     #  一般不用 坑多
2. get_sreenshoot_as_file  # 保存網頁截圖
3. get_sreenshoot_as_png   #獲取二進制數據流
4.get_sreenshoot_as_base64  # base64編碼原始數據

2.allure的鈎子函數

Hooks 函數獲取用例執行結果(pytest_runtest_makereport)

看一下ruuner的源碼  pytest執行測試原理   setup  call  teardown

_pytest.runner

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 的執行結果

運行實例

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

運行結果如下

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內容如下

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執行失敗了,setup的執行結果的failed,后面的call用例和teardown都不會執行了

 

 此時用例的狀態是: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 后置操作")

運行結果

 

 

3.allure報告集成錯誤截圖

需要使用conftest.py文件,conftest.py需要存在在測試目錄中,文件名不能變更,可以根據模塊創建層級嵌套。

具體參照pytest的官方文檔

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    '''
    hook pytest失敗
    :param item:
    :param call:
    :return:
    '''
    # execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()
    # we only look at actual failing test calls, not setup/teardown
    if rep.when == "call" and rep.failed:
        mode = "a" if os.path.exists("failures") else "w"
        with open("failures", mode) as f:
            # let's also access a fixture for the fun of it
            if "tmpdir" in item.fixturenames:
                extra = " (%s)" % item.funcargs["tmpdir"]
            else:
                extra = ""
            f.write(rep.nodeid + extra + "\n")
        # pic_info = adb_screen_shot()
        with allure.step('添加失敗截圖...'):
            allure.attach(driver.get_screenshot_as_png(), "失敗截圖", allure.attachment_type.PNG)
 

 

4.Pytest+Allure+Selenuim+異常截屏+Allure日志

需要使用conftest.py文件,conftest.py需要存在在測試目錄中,文件名不能變更,可以根據模塊創建層級嵌套。具體參照pytest的官方文檔

https://blog.csdn.net/cc8945203/article/details/103765505?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM