欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python測試框架pytest核心庫pluggy詳解

 更新時(shí)間:2022年08月04日 16:37:58   作者:三水  
這篇文章主要為大家介紹了Python測試框架pytest核心庫pluggy使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

代碼案例

import pluggy
# HookspecMarker 和 HookimplMarker 實(shí)質(zhì)上是一個(gè)裝飾器帶參數(shù)的裝飾器類,作用是給函數(shù)增加額外的屬性設(shè)置
hookspec = pluggy.HookspecMarker("myproject")
hookimpl = pluggy.HookimplMarker("myproject")
'''
HookspeckMarker:
    傳入firstresult=True時(shí),獲取第一個(gè)plugin執(zhí)行結(jié)果后就停止繼續(xù)執(zhí)行 @hookspec(firstresult=True)
    historic - 表示這個(gè) hook 是需要保存call history 的,當(dāng)有新的 plugin 注冊的時(shí)候,需要回放歷史
hookimpl:
    當(dāng)傳入tryfirst=True時(shí),表示這個(gè)類的hook函數(shù)會(huì)優(yōu)先執(zhí)行,其他的仍然按照后進(jìn)先出的順序執(zhí)行
    當(dāng)傳入trylast=True,表示當(dāng)前插件的hook函數(shù)會(huì)盡可能晚的執(zhí)行,其他的仍然按照后進(jìn)先出的順序執(zhí)行
    當(dāng)傳入hookwrapper=True時(shí),需要在這個(gè)plugin中實(shí)現(xiàn)一個(gè)yield,plugin先執(zhí)行yield之前的代碼,
        然后去執(zhí)行其他的pluggin,然后再回來執(zhí)行yield之后的代碼,同時(shí)通過yield可以獲取到其他插件執(zhí)行的結(jié)果
'''
# 定義自己的Spec,這里可以理解為定義接口類
class MySpec:
    # hookspec 是一個(gè)裝飾類中的方法的裝飾器,為此方法增額外的屬性設(shè)置,這里myhook可以理解為定義了一個(gè)接口
    # 會(huì)給當(dāng)前方法添加屬性  鍵為 {self.project_name + "_spec"} 值是裝飾器傳入的參數(shù)
    @hookspec
    def myhook(self, arg1, arg2):
        pass
# 定義了一個(gè)插件
class Plugin_1:
    # 插件中實(shí)現(xiàn)了上面定義的接口,同樣這個(gè)實(shí)現(xiàn)接口的方法用 hookimpl裝飾器裝飾,功能是返回兩個(gè)參數(shù)的和
    @hookimpl
    def myhook(self, arg1, arg2):
        print("inside Plugin_1.myhook()")
        return arg1 + arg2
# 定義第二個(gè)插件
class Plugin_2:
    # 插件中實(shí)現(xiàn)了上面定義的接口,同樣這個(gè)實(shí)現(xiàn)接口的方法用 hookimpl裝飾器裝飾,功能是返回兩個(gè)參數(shù)的差
    @hookimpl(hookwrapper=True)
    def myhook(self, arg1, arg2):
        out = yield
        print("inside Plugin_2.myhook()")
        return arg1 - arg2
# 實(shí)例化一個(gè)插件管理的對象,注意這里的名稱要與文件開頭定義裝飾器的時(shí)候的名稱一致
pm = pluggy.PluginManager("myproject")
# 將自定義的接口類加到鉤子定義中去
pm.add_hookspecs(MySpec)
# 注冊定義的兩個(gè)插件
pm.register(Plugin_1())
pm.register(Plugin_2())
# 通過插件管理對象的鉤子調(diào)用方法,這時(shí)候兩個(gè)插件中的這個(gè)方法都會(huì)執(zhí)行,而且遵循后注冊先執(zhí)行即LIFO的原則,兩個(gè)插件的結(jié)果講義列表的形式返回
results = pm.hook.myhook(arg1=1, arg2=2)
print(results)

實(shí)例化:

  • 初始化一些參數(shù),如_name2plugin:存放后續(xù)注冊 plugin

添加到鉤子定義中 (add_hookspecs)

  • 將定義的類已參數(shù)的方式傳遞進(jìn)去 (module_or_class)
  • 遍歷類中全部的方法
  • 判斷: getattr(method, self.project_name + "_spec", None),判斷類方法中是否有當(dāng)前定義 myproject+spec 的屬性,
    • 如果有則返回裝飾器所得到的參數(shù),沒有則返回 None,其實(shí)就是判斷有沒有被@hookspec裝飾,因?yàn)檠b飾了會(huì)設(shè)置上 myproject+spec 這個(gè)屬性以及相對應(yīng)的值
  • 如果有被裝飾: 判斷一下 self.hook 中是否以及存在了這個(gè) spec
  • 如果不存在: 創(chuàng)建一個(gè)_HookCaller(spec 名字,_hookexec(本質(zhì)就是一個(gè)執(zhí)行 hook 的方法),傳遞進(jìn)來的 spec 對象,第三步獲得的參數(shù),也就是通過裝飾器 set 到方法中的一些參數(shù)) 對象
    • init: 判斷 spec 對象是否為空,如果不為空:
      • ? 先判斷參數(shù)是否存在,如果存在,創(chuàng)建一個(gè) HookSpec 給 self.spec,傳遞參數(shù)為 當(dāng)前 spec 對象,當(dāng)前 spec 名字,參數(shù),self.function 就是對應(yīng)的那個(gè)被裝飾的方法,最后判斷一下這個(gè) spec 需不需要保存歷史,如果需要,初始化一個(gè)列表
  • 將上面初始化的對象,通過 setattr 的方式存在到 self.hook 中,名字就是被裝飾方法的名字,值是剛剛創(chuàng)建的對象
  • 最后會(huì)在 names 的列表中把這個(gè)添加的方法的名字添加進(jìn)去,判斷一個(gè) names 是否為空,如果為空,則拋出異常
  • 添加 add_hookspecs 的步驟全部完成

注冊插件 register

注冊插件 (register): 傳遞實(shí)現(xiàn)插件的實(shí)體類對象

  • 判斷是否傳遞插件名字,如果沒傳,就獲取對象的name屬性,如果還沒有就直接用 id() 生產(chǎn)一個(gè)隨機(jī)字符串做當(dāng)前對象在插件中的名字

  • 判斷名字是否存在,或者是否已被注冊: self._name2plugin 和 self._plugin2hookcaller,前者是用 plugin_name 做 key,后者是用 plugin object 做 key,判斷是否已經(jīng)注冊過重復(fù)的 plugin

  • self._name2plugin[plugin_name(插件名字)] = plugin(傳遞的實(shí)體類對象)
    self._plugin2hookcallers[plugin(傳遞的實(shí)體類對象)] = hookcallers = [],其實(shí)就是初始化一下 self._plugin2hookcallers[plugin],因?yàn)榱斜淼囊脗鬟f,所有直接修改 hookcallers 也可以作用在 self 中

  • 遍歷實(shí)體類對象的方法列表,判斷是否被 impl 裝飾:

    • a.先獲取到方法對象
    • b.判斷對象是否是內(nèi)置函數(shù)、函數(shù)、方法或者方法描述符,如果不是直接返回
    • c.獲取該方法的屬性 hook 對象創(chuàng)建時(shí)傳遞的名字 (myproject) + "_impl" ,沒有則返回 None
    • d.判斷獲取到的值是不是 None 并且不是一個(gè)字典,則將獲取到的 res 賦值為 None
    • e. 最后返回 res,其實(shí)就是 hookimpl 裝飾器,如果你不給值就給一堆默認(rèn)值
  • 先判斷參數(shù)列表是否為空: 如果不為空,進(jìn)行設(shè)置默認(rèn)值 (其實(shí)正常是不會(huì)出現(xiàn)沒有值的情況),然后從實(shí)體類對象中獲取到該方法的對象

    • 在創(chuàng)建一個(gè)新的對象 (HookImpl):init(self,傳遞進(jìn)來的實(shí)體類對象,hook 名字 (第一步獲取或者 id 生成),method 對象,第四步返回的參數(shù)字典),并且將參數(shù)列表跟新到 self.dict
  • 判斷 self.hook 中是否以及注冊了當(dāng)前插件 (就是 add_hookspecs 注冊的 spec 中是否有當(dāng)前方法)

    • 如果沒有注冊,會(huì)直接注冊一個(gè),這樣注冊 specmodule_or_class 參數(shù)會(huì)為空,意為著不會(huì)有額外的一些參數(shù) eg:tryfirst
  • hook.has_spec() 判斷注冊 spec 的 spec 屬性不為空

    • self._verify_hook(hook(spec 對象), hookimpl(插件對象)) a.先判斷當(dāng)前對象中是否有 (_call_history 屬性),歷史 和是否 需要使用 yield b. 判斷 hookimpl 和 hook.spec 的參數(shù)列表是否相等,如果不相等報(bào)錯(cuò)
  • hook._maybe_apply_history(hookimpl)
    a.判斷是否有_call_history 這個(gè)屬性

  • hook._add_hookimpl(hookimpl):
    a.判斷是否為 hookwrapper 為 True,添加到不同的 wrappers 中
    b.判斷是否有 trylast tryfirst 屬性,將 hookimpl 存放到對應(yīng)位置
    c.將 hook 添加到 hookcallers 中

  • 遍歷結(jié)束后,返回 plugin_name(第一步產(chǎn)生)

運(yùn)行插件 pm.hook.myhook

運(yùn)行插件 pm.hook.myhook(arg1=1, arg2=2):本質(zhì)就是調(diào)用對象的call方法

  • 先判斷是否有順序參數(shù),如果有直接報(bào)錯(cuò)
  • 在判斷是否有_call_history 這個(gè)屬性
  • 判斷實(shí)際傳入?yún)?shù),是否和插件需要參數(shù)一樣
  • self._hookexec(self(hook 對象), self.get_hookimpls()(全部的已經(jīng)注冊的插件), kwargs(傳入的參數(shù)))

self._inner_hookexec(hook(hook 對象), methods(插件), kwargs(參數(shù)))

# 實(shí)際調(diào)用,也就是hook.multicall的方法
self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
            methods,
            kwargs,
            firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
        )
  • _multicall(hook_impls(插件), caller_kwargs(參數(shù)), firstresult=False(@hookspec傳入,默認(rèn) False))

1. 先將 hook_impls 變成一個(gè)可迭代對象 (reversed(hook_impls))

2. 先把順序參數(shù)的參數(shù)列表,拿到 (列表推導(dǎo)式)

3. 判斷需不需要將其他插件執(zhí)行的結(jié)果傳遞進(jìn)去

- 需要
- 先從 hook_impl 中拿出對應(yīng)的方法并且傳遞參數(shù),執(zhí)行關(guān)鍵字 yield 前面部分
- 然后 next()
- 最后將這個(gè)方法添加到 teardowns 列表中去

- 不需要
- 先從 hook_impl 中拿出對于的方法并且傳遞參數(shù)
- 判斷執(zhí)行后的返回值是不是為空,不為空則添加到 results 列表中
- 最后判斷是否有 firstresult 屬性,如果有直接結(jié)束循環(huán)

4. 最后執(zhí)行 (finally 中代碼)

- 如果 firstresult 為 true,那么直接返回第一個(gè)插件返回的結(jié)果即可
- 執(zhí)行 teardowns 列表中的需要最后執(zhí)行的插件
- 通過迭代器的 send 方法,將上幾個(gè)插件的結(jié)果傳遞進(jìn)去

5. 返回 result 對象 :會(huì)判斷是否有報(bào)錯(cuò) 如果沒有直接返回結(jié)果列表,如果有報(bào)錯(cuò)會(huì)拋出異常

以上就是Python測試框架pytest核心庫pluggy詳解的詳細(xì)內(nèi)容,更多關(guān)于Python pytest庫pluggy的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python編程使用DRF實(shí)現(xiàn)一次性驗(yàn)證碼OTP

    Python編程使用DRF實(shí)現(xiàn)一次性驗(yàn)證碼OTP

    今天講一下如何用 Django REST framework[1](DRF) 來實(shí)現(xiàn) OTP,閱讀本文需要一定的 DRF 的基礎(chǔ)知識,有需要的朋友可以借鑒參考下
    2021-09-09
  • 詳解如何從TensorFlow的mnist數(shù)據(jù)集導(dǎo)出手寫體數(shù)字圖片

    詳解如何從TensorFlow的mnist數(shù)據(jù)集導(dǎo)出手寫體數(shù)字圖片

    這篇文章主要介紹了詳解如何從TensorFlow的mnist數(shù)據(jù)集導(dǎo)出手寫體數(shù)字圖片,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • python?replace?空格數(shù)據(jù)處理的實(shí)現(xiàn)

    python?replace?空格數(shù)據(jù)處理的實(shí)現(xiàn)

    本文主要介紹了python?replace?空格數(shù)據(jù)處理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Python用for循環(huán)實(shí)現(xiàn)九九乘法表

    Python用for循環(huán)實(shí)現(xiàn)九九乘法表

    本文通過實(shí)例代碼給大家介紹了Python用for循環(huán)實(shí)現(xiàn)九九乘法表的方法,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05
  • python函數(shù)的5種參數(shù)詳解

    python函數(shù)的5種參數(shù)詳解

    昨天看《Python核心編程》的時(shí)候,剛好看到了函數(shù)部分,于是順勢將目前接觸到的集中參數(shù)類型都總結(jié)一下吧^^
    2017-02-02
  • Python實(shí)現(xiàn)調(diào)用攝像頭拍攝照片

    Python實(shí)現(xiàn)調(diào)用攝像頭拍攝照片

    這篇文章主要為大家詳細(xì)介紹了如何利用Python實(shí)現(xiàn)調(diào)用攝像頭拍攝照片以及郵箱收集功能,文中的示例代碼講解詳細(xì),感興趣的可以動(dòng)手嘗試一下
    2022-06-06
  • Pycharm新建項(xiàng)目時(shí)報(bào)錯(cuò)解決辦法

    Pycharm新建項(xiàng)目時(shí)報(bào)錯(cuò)解決辦法

    pycharm可以很方便的管理Python的解釋器(如果安裝了多個(gè)的話),以及第三方模塊,包,下面這篇文章主要給大家介紹了關(guān)于Pycharm新建項(xiàng)目時(shí)報(bào)錯(cuò)解決的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • 手把手教你實(shí)現(xiàn)PyTorch的MNIST數(shù)據(jù)集

    手把手教你實(shí)現(xiàn)PyTorch的MNIST數(shù)據(jù)集

    本文主要介紹了PyTorch的MNIST數(shù)據(jù)集,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • python中異常捕獲方法詳解

    python中異常捕獲方法詳解

    異常信息的獲取對于程序的調(diào)試非常重要,可以有助于快速定位有錯(cuò)誤程序語句的位置。下面介紹幾種python中獲取異常信息的方法,希望小伙伴們能夠喜歡
    2017-03-03
  • python如何寫出表白程序

    python如何寫出表白程序

    在本篇文章里小編給大家分享的是一篇關(guān)于python實(shí)現(xiàn)表白程序的代碼實(shí)例,需要的朋友們可以參考下。
    2020-06-06

最新評論