成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

pytest插件探索——hook開發(fā)

shiguibiao / 2424人閱讀

摘要:所有的函數(shù)都使用的命名規(guī)則,以便于查找并且同其他函數(shù)區(qū)分開來。用來每個(gè),保證被正確的定義。里還有一個(gè)選項(xiàng),用來表示這個(gè)函數(shù)是個(gè)函數(shù)。自動(dòng)注冊(cè)插件除了常規(guī)的方法注冊(cè)插件,同時(shí)提供了方法,允許通過自動(dòng)注冊(cè)插件。

前言

參考官方的這篇文章,我嘗試翻譯其中一些重點(diǎn)部分,并且拓展了相關(guān)的pluggy部分的知識(shí)。由于pytest是在pluggy基礎(chǔ)上構(gòu)建的,強(qiáng)烈建議先閱讀一下pluggy的官方文檔,這樣理解起來更加容易一點(diǎn)。

正文

conftest.py可以作為最簡(jiǎn)單的本地plugin調(diào)用一些hook函數(shù),以此來做些強(qiáng)化功能。

pytest整個(gè)框架通過調(diào)用如下定義良好的hooks來實(shí)現(xiàn)配置,收集,執(zhí)行和報(bào)告這些過程:

內(nèi)置plugins:從代碼內(nèi)部的_pytest目錄加載;

外部插件(第三方插件):通過setuptools entry points機(jī)制發(fā)現(xiàn)的第三方插件模塊;

conftest.py形式的本地插件:測(cè)試目錄下的自動(dòng)模塊發(fā)現(xiàn)機(jī)制;

原則上,每個(gè)hook都是一個(gè) 1:N 的python函數(shù)調(diào)用, 這里的 N 是對(duì)一個(gè)給定hook的所有注冊(cè)調(diào)用數(shù)。所有的hook函數(shù)都使用pytest_xxx的命名規(guī)則,以便于查找并且同其他函數(shù)區(qū)分開來。

decorrator

pluggy里提供了兩個(gè)decorator helper類,分別是HookspecMarkerHookimplMarker,通過使用相同的project_name參數(shù)初始化得到對(duì)應(yīng)的裝飾器,后續(xù)可以用這個(gè)裝飾器將函數(shù)標(biāo)記為hookspechookimpl。

hookspec

hook specification (hookspec)用來validate每個(gè)hookimpl,保證hookimpl被正確的定義。

hookspec 通過 add_hookspecs()方法加載,一般在注冊(cè)hookimpl之前先加載;

hookimpl

hook implementation (hookimpl) 是一個(gè)被恰當(dāng)標(biāo)記過的回調(diào)函數(shù)。hookimpls 通過register()方法加載。

注:為了保證hookspecs在項(xiàng)目里可以不斷演化, hookspec里的參數(shù)對(duì)于hookimpls是可選的,即可以定義少于spec里定義數(shù)量的參數(shù)。

hookwrapper

hookimpl 里還有一個(gè)hookwrapper選項(xiàng),用來表示這個(gè)函數(shù)是個(gè)hookwrapper函數(shù)。hookwrapper函數(shù)可以在普通的非wrapper的hookimpls執(zhí)行的前后執(zhí)行一些其他代碼, 類似于@contextlib.contextmanager,hookwrapper必須在它的主體包含單一的yield,用來實(shí)現(xiàn)生成器函數(shù),例如:

import pytest

@pytest.hookimpl(hookwrapper=True)
def pytest_pyfunc_call(pyfuncitem):
    do_something_before_next_hook_executes()

    outcome = yield
    # outcome.excinfo may be None or a (cls, val, tb) tuple

    res = outcome.get_result()  # will raise if outcome was exception

    post_process_result(res)

    outcome.force_result(new_res)  # to override the return value to the plugin system

生成器發(fā)送一個(gè) pluggy.callers._Result對(duì)象 , 這個(gè)對(duì)象可以在 yield表達(dá)式里指定并且通過 force_result()或者get_result() 方法重寫或者拿到最終結(jié)果。

注:hookwrapper不能返回結(jié)果 (跟所有的生成器函數(shù)一樣);

hookimpl的調(diào)用順序

默認(rèn)情況下,hook的調(diào)用順序遵循注冊(cè)時(shí)的順序LIFO(后進(jìn)先出),hookimpl允許通過tryfirst, trylast*選項(xiàng)調(diào)整這一項(xiàng)順序。

舉個(gè)例子,對(duì)于如下的代碼:

# Plugin 1
@pytest.hookimpl(tryfirst=True)
def pytest_collection_modifyitems(items):
    # will execute as early as possible
    ...


# Plugin 2
@pytest.hookimpl(trylast=True)
def pytest_collection_modifyitems(items):
    # will execute as late as possible
    ...


# Plugin 3
@pytest.hookimpl(hookwrapper=True)
def pytest_collection_modifyitems(items):
    # will execute even before the tryfirst one above!
    outcome = yield
    # will execute after all non-hookwrappers executed

執(zhí)行順序如下:

Plugin3的pytest_collection_modifyitems先調(diào)用,直到y(tǒng)ield點(diǎn),因?yàn)檫@是一個(gè)hook warpper。

Plugin1的pytest_collection_modifyitems被調(diào)用,因?yàn)橛?tryfirst=True參數(shù)。

Plugin2的pytest_collection_modifyitems被調(diào)用,因?yàn)橛?trylast=True參數(shù) (不過即使沒有這個(gè)參數(shù)也會(huì)排在tryfirst標(biāo)記的plugin后面)。

Plugin3的pytest_collection_modifyitems調(diào)用yield后面的代碼. yield接收非Wrapper的result返回. Wrapper函數(shù)不應(yīng)該修改這個(gè)result。

當(dāng)然也可以同時(shí)將 tryfirsttrylasthookwrapper=True 混用,這種情況下它將影響hookwrapper之間的調(diào)用順序.

hook執(zhí)行結(jié)果處理和firstresult選項(xiàng)

默認(rèn)情況下,調(diào)用一個(gè)hook會(huì)使底層的hookimpl函數(shù)在一個(gè)循環(huán)里按順序執(zhí)行,并且將其非空的執(zhí)行結(jié)果添加到一個(gè)list里面。例外的是,hookspec里有一個(gè)firstresult選項(xiàng),如果指定這個(gè)選項(xiàng)為true,那么得到第一個(gè)返回非空的結(jié)果的hookimpl執(zhí)行后就直接返回,后續(xù)的hookimpl將不在被執(zhí)行,參考后面的例子。

注: hookwrapper還是正常的執(zhí)行

hook的調(diào)用

每一個(gè)pluggy.PluginManager 都有一個(gè)hook屬性, 可以通過調(diào)用這個(gè)屬性的call函數(shù)來調(diào)用hook,需要注意的是,調(diào)用時(shí)必須使用關(guān)鍵字參數(shù)語法來調(diào)用。

請(qǐng)看下面這個(gè)firstresult和hook調(diào)用例子:

from pluggy import PluginManager, HookimplMarker, HookspecMarker

hookspec = HookspecMarker("myproject")
hookimpl = HookimplMarker("myproject")


class MySpec1(object):
    @hookspec
    def myhook(self, arg1, arg2):
        pass


class MySpec2(object):
    # 這里將firstresult設(shè)置為True
    @hookspec(firstresult=True)
    def myhook(self, arg1, arg2):
        pass


class Plugin1(object):
    @hookimpl
    def myhook(self, arg1, arg2):
        """Default implementation.
        """
        return 1


class Plugin2(object):
    # hookimpl可以定義少于hookspec里定義數(shù)量的參數(shù),這里只定義arg1
    @hookimpl
    def myhook(self, arg1):
        """Default implementation.
        """
        return 2


class Plugin3(object):
    # 同上,甚至可以不定義hookspec里的參數(shù) 
    @hookimpl
    def myhook(self):
        """Default implementation.
        """
        return 3


pm1 = PluginManager("myproject")
pm2 = PluginManager("myproject")
pm1.add_hookspecs(MySpec1)
pm2.add_hookspecs(MySpec2)
pm1.register(Plugin1())
pm1.register(Plugin2())
pm1.register(Plugin3())
pm2.register(Plugin1())
pm2.register(Plugin2())
pm2.register(Plugin3())
# hook調(diào)用必須使用關(guān)鍵字參數(shù)的語法
print(pm1.hook.myhook(arg1=None, arg2=None))
print(pm2.hook.myhook(arg1=None, arg2=None))

得到結(jié)果如下:

[3, 2, 1]
3

可以看到,由于pm2里的hookspec里有firstresult參數(shù),在得到3這個(gè)非空結(jié)果時(shí)就直接返回了。

自動(dòng)注冊(cè)插件

除了常規(guī)的register()方法注冊(cè)插件,pluggy同時(shí)提供了 load_setuptools_entrypoints()方法,允許通過 setuptools entry points 自動(dòng)注冊(cè)插件。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/43436.html

相關(guān)文章

  • pytest插件探索——hook workflow

    摘要:會(huì)調(diào)用向打印一些環(huán)境信息,比如插件版本,版本,操作平臺(tái)這些等。在執(zhí)行之后調(diào)用執(zhí)行的過程是否執(zhí)行取決于是否需要?jiǎng)?chuàng)建執(zhí)行的過程如果有。所有測(cè)試執(zhí)行完畢之后,返回之前的階段。結(jié)束以后,整個(gè)退出之前的階段。 pytest插件開發(fā)需要熟悉一些常用的hook函數(shù),官方對(duì)于這些hook有一份簡(jiǎn)略的文檔(目前除了小部分hook目前缺乏文檔外,見這個(gè)issue),但是各個(gè)hook的調(diào)用邏輯沒有一個(gè)直觀的...

    pubdreamcc 評(píng)論0 收藏0
  • 2021-09-03-接口自動(dòng)化-python+requests+pytest+csv+yaml+a

    摘要:本套代碼和邏輯是本人的勞動(dòng)成果,如果有轉(zhuǎn)載需要標(biāo)注,非常適合公司做項(xiàng)目的同學(xué)小白也可以學(xué)哦接口自動(dòng)化項(xiàng)目目錄公共方法的封裝如果不用配置文件可以使用這個(gè)方法進(jìn)行封裝但是有一定的缺陷可以不使用字典。這是在正常的命令行解析之前發(fā)生的。 ...

    李昌杰 評(píng)論0 收藏0
  • 帶你深入理解自動(dòng)化測(cè)試框架Pytest的配置文件!

    摘要:其中用到編程等,還需要花更多的精力去深入學(xué)習(xí),當(dāng)每項(xiàng)技能都能掌握到一定深度,才能稱為一個(gè)完整的知識(shí)體系。 都有哪些種類的配置文件 pytest.ini:pytes...

    wayneli 評(píng)論0 收藏0
  • Pytest+Allure使用問題記錄

    摘要:?jiǎn)栴}大部分問題是因?yàn)榘惭b了導(dǎo)致的比如此時(shí)需要先卸載然后再安裝包已經(jīng)安裝過的不用重復(fù)安裝。版本問題類似于這種一般是因?yàn)榘姹咎邔?dǎo)致建議卸載現(xiàn)有版本并安裝較低版本的。后續(xù)重裝低版本出現(xiàn)如下報(bào)錯(cuò)重裝最新版本并重裝包 ...

    番茄西紅柿 評(píng)論0 收藏2637
  • 利用xdist實(shí)現(xiàn)自動(dòng)化測(cè)試用例并行執(zhí)行

    摘要:在測(cè)試行業(yè),如果利用作為腳本語言開發(fā)自動(dòng)化測(cè)試用例,可用的框架有等主流可供選擇,個(gè)人感覺較之和應(yīng)該算是現(xiàn)階段最靈活,功能最全面,擴(kuò)展最豐富的框架了。不知道各位在做自動(dòng)化的時(shí)候有沒有遇到過用例數(shù)過多,單機(jī)執(zhí)行效率不高的困擾。 在測(cè)試行業(yè),如果利用python作為腳本語言開發(fā)自動(dòng)化測(cè)試用例,可用...

    tabalt 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<