亚洲国产日韩人妖另类,久久只有这里有精品热久久,依依成人精品视频在线观看,免费国产午夜视频在线

      
      

        頭條漲薪秘籍-全網(wǎng)沒有之一的pytest 玩轉(zhuǎn)數(shù)據(jù)驅(qū)動(dòng)測試框架

        頭條漲薪秘籍-全網(wǎng)沒有之一的pytest 玩轉(zhuǎn)數(shù)據(jù)驅(qū)動(dòng)測試框架

        前言:

        嗨咯鐵汁們,很久不見,我還是你們的老朋友,這里也感謝各位小伙伴的點(diǎn)贊和關(guān)注,你們的三連是我最大的動(dòng)力哈,我也不會(huì)辜負(fù)各位的期盼,這里呢給大家出了一個(gè)我們廢話少說直接開始正文

        【文章的末尾給大家留下了大量的福利】

        編輯

        ytest架構(gòu)是什么?

        首先,來看一個(gè) pytest 的例子:

        def test_a(): print(123)

        collected 1 itemtest_a.py . [100%]============ 1 passed in 0.02s =======================

        輸出結(jié)果很簡單:收集到 1 個(gè)用例,并且這條測試用例執(zhí)行通過。此時(shí)思考兩個(gè)問題:1.pytest 如何收集到用例的?2.pytest 如何把 python 代碼,轉(zhuǎn)換成 pytest 測試用例(又稱 item) ?

        pytest如何做到收集到用例的?

        這個(gè)很簡單,遍歷執(zhí)行目錄,如果發(fā)現(xiàn)目錄的模塊中存在符合“ pytest 測試用例要求的 python 對(duì)象”,就將之轉(zhuǎn)換為 pytest 測試用例。比如編寫以下 hook 函數(shù)

        def pytest_collect_file(path, parent): print(“hello”, path)

        hello C:UsersyuruoDesktopmpmp123mpestcase__init__.pyhello C:UsersyuruoDesktopmpmp123mpestcaseconftest.pyhello C:UsersyuruoDesktopmpmp123mpestcaseest_a.py

        會(huì)看到所有文件內(nèi)容。

        pytest 像是包裝盒,將 python 對(duì)象包裹起來,比如下圖

        當(dāng)寫好 python 代碼時(shí):

        def test_a: print(123)

        會(huì)被包裹成 Function :

        可以從 hook 函數(shù)中查看細(xì)節(jié):

        def pytest_collection_modifyitems(session, config, items): pass

        于是,理解包裹過程就是解開迷題的關(guān)鍵。pytest 是如何包裹 python 對(duì)象的?下面代碼只有兩行,看似簡單,但暗藏玄機(jī)!

        def test_a: print(123)

        把代碼位置截個(gè)圖,如下:

        我們可以說,上述代碼是處于“testcase包”下的 “test_a.py模塊”的“test_a函數(shù)”, pytest 生成的測試用例也要有這些信息:處于“testcase包”下的 “test_a.py模塊”的“test_a測試用例:把上述表達(dá)轉(zhuǎn)換成下圖:pytest 使用 parent 屬性表示上圖層級(jí)關(guān)系,比如 Module 是 Function 的上級(jí), Function 的 parent 屬性如下:

        : parent:

        當(dāng)然 Module 的 parent 就是 Package:

        : parent:

        這里科普一下,python 的 package 和 module 都是真實(shí)存在的對(duì)象,你可以從 obj 屬性中看到,比如 Module 的 obj 屬性如下:

        如果理解了 pytest 的包裹用途,非常好!我們進(jìn)行下一步討論:如何構(gòu)造 pytest 的 item ?

        以下面代碼為例:

        def test_a: print(123)

        構(gòu)造 pytest 的 item ,需要:3.構(gòu)建 Package4.構(gòu)建 Module5.構(gòu)建 Function以構(gòu)建 Function 為例,需要調(diào)用其from_parent()方法進(jìn)行構(gòu)建,其過程如下圖:

        ,就可以猜測出,“構(gòu)建 Function”一定與其 parent 有不小聯(lián)系!又因?yàn)?Function 的 parent 是 Module :根據(jù)下面 Function 的部分代碼(位于 python.py 文件):

        class Function(PyobjMixin, nodes.Item): # 用于創(chuàng)建測試用例 @classmethod def from_parent(cls, parent, **kw): “””The public constructor.””” return super().from_parent(parent=parent, **kw) # 獲取實(shí)例 def _getobj(self): assert self.parent is not None return getattr(self.parent.obj, self.originalname) # type: ignore[attr-defined] # 運(yùn)行測試用例 def runtest(self) -> None: “””Execute the underlying test function.””” self.ihook.pytest_pyfunc_call(pyfuncitem=self)

        得出結(jié)論,可以利用 Module 構(gòu)建 Function!其調(diào)用偽代碼如下:

        Function.from_parent(Module)

        既然可以利用 Module 構(gòu)建 Function, 那如何構(gòu)建 Module ?當(dāng)然是利用 Package 構(gòu)建 Module!

        Module.from_parent(Package)

        既然可以利用 Package 構(gòu)建 Module 那如何構(gòu)建 Package ?別問了,快成套娃了,請(qǐng)看下圖調(diào)用關(guān)系:

        編輯

        pytest 從 Config 開始,層層構(gòu)建,直到 Function !Function 是 pytest 的最小執(zhí)行單元。手動(dòng)構(gòu)建 item 就是模擬 pytest 構(gòu)建 Function 的過程。也就是說,需要?jiǎng)?chuàng)建 Config ,然后利用 Config 創(chuàng)建 Session ,然后利用 Session 創(chuàng)建 Package ,…,最后創(chuàng)建 Function。

        其實(shí)沒這么復(fù)雜, pytest 會(huì)自動(dòng)創(chuàng)建好 Config, Session和 Package ,這三者不用手動(dòng)創(chuàng)建。

        比如編寫以下 hook 代碼,打斷點(diǎn)查看其 parent 參數(shù):

        def pytest_collect_file(path, parent): pass

        如果遍歷的路徑是某個(gè)包(可從path參數(shù)中查看具體路徑),比如下圖的包:

        編寫如下代碼即可構(gòu)建 pytest 的 Module ,如果發(fā)現(xiàn)是 yaml 文件,就根據(jù) yaml 文件內(nèi)容動(dòng)態(tài)創(chuàng)建 Module 和 module :

        from _pytest.python import Module, Packagedef pytest_collect_file(path, parent): if path.ext == “.yaml”: pytest_module = Module.from_parent(parent, fspath=path) # 返回自已定義的 python module pytest_module._getobj = lambda : MyModule return pytest_module

        需要注意,上面代碼利用猴子補(bǔ)丁改寫了 _getobj 方法,為什么這么做?Module 利用 _getobj 方法尋找并導(dǎo)入(import語句) path 包下的 module ,其源碼如下:

        # _pytest/python.py Moduleclass Module(nodes.File, PyCollector): def _getobj(self): return self._importtestmodule()def _importtestmodule(self): # We assume we are only called once per module. importmode = self.config.getoption(“–import-mode”) try: # 關(guān)鍵代碼:從路徑導(dǎo)入 module mod = import_path(self.fspath, mode=importmode) except SyntaxError as e: raise self.CollectError( ExceptionInfo.from_current().getrepr(style=”short”) ) from e # 省略部分代碼…

        但是,如果使用數(shù)據(jù)驅(qū)動(dòng),即用戶創(chuàng)建的數(shù)據(jù)文件 test_parse.yaml ,它不是 .py 文件,不會(huì)被 python 識(shí)別成 module (只有 .py 文件才能被識(shí)別成 module)。這時(shí),就不能讓 pytest 導(dǎo)入(import語句) test_parse.yaml ,需要?jiǎng)討B(tài)改寫 _getobj ,返回自定義的 module !因此,可以借助 lambda 表達(dá)式返回自定義的 module :

        lambda : MyModule

        這就涉及元編程技術(shù):動(dòng)態(tài)構(gòu)建 python 的 module ,并向 module 中動(dòng)態(tài)加入類或者函數(shù):

        import types# 動(dòng)態(tài)創(chuàng)建 modulemodule = types.ModuleType(name)def function_template(*args, **kwargs): print(123)# 向 module 中加入函數(shù)setattr(module, “test_abc”, function_template)

        綜上,將自己定義的 module 放入 pytest 的 Module 中即可生成 item :

        # conftest.pyimport typesfrom _pytest.python import Moduledef pytest_collect_file(path, parent): if path.ext == “.yaml”: pytest_module = Module.from_parent(parent, fspath=path) # 動(dòng)態(tài)創(chuàng)建 module module = types.ModuleType(path.purebasename) def function_template(*args, **kwargs): print(123) # 向 module 中加入函數(shù) setattr(module, “test_abc”, function_template) pytest_module._getobj = lambda: module return pytest_module

        創(chuàng)建一個(gè) yaml 文件,使用 pytest 運(yùn)行:

        ======= test session starts ====platform win32 — Python 3.8.1, pytest-6.2.4, py-1.10.0, pluggy-0.13.1rootdir: C:UsersyuruoDesktopmpplugins: allure-pytest-2.8.11, forked-1.3.0, rerunfailures-9.1.1, timeout-1.4.2, xdist-2.2.1collected 1 itemtest_a.yaml 123.======= 1 passed in 0.02s =====PS C:UsersyuruoDesktopmp>

        現(xiàn)在停下來,回顧一下,我們做了什么?借用 pytest hook ,將 .yaml 文件轉(zhuǎn)換成 python module。

        作為一個(gè)數(shù)據(jù)驅(qū)動(dòng)測試框架,我們沒做什么?沒有解析 yaml 文件內(nèi)容!上述生成的 module ,其內(nèi)的函數(shù)如下:

        def function_template(*args, **kwargs): print(123)

        只是簡單打印 123 。數(shù)據(jù)驅(qū)動(dòng)測試框架需要解析 yaml 內(nèi)容,根據(jù)內(nèi)容動(dòng)態(tài)生成函數(shù)或類。比如下面 yaml 內(nèi)容:

        test_abc: – print: 123

        表達(dá)的含義是“定義函數(shù) test_abc,該函數(shù)打印 123”??梢岳?yaml.safe_load 加載 yaml 內(nèi)容,并進(jìn)行關(guān)鍵字解析,其中path.strpath代表 yaml 文件的地址:

        import typesimport yamlfrom _pytest.python import Moduledef pytest_collect_file(path, parent): if path.ext == “.yaml”: pytest_module = Module.from_parent(parent, fspath=path) # 動(dòng)態(tài)創(chuàng)建 module module = types.ModuleType(path.purebasename) # 解析 yaml 內(nèi)容 with open(path.strpath) as f: yam_content = yaml.safe_load(f) for function_name, steps in yam_content.items(): def function_template(*args, **kwargs): “”” 函數(shù)模塊 “”” # 遍歷多個(gè)測試步驟 [print: 123, print: 456] for step_dic in steps: # 解析一個(gè)測試步驟 print: 123 for step_key, step_value in step_dic.items(): if step_key == “print”: print(step_value) # 向 module 中加入函數(shù) setattr(module, function_name, function_template) pytest_module._getobj = lambda: module return pytest_module

        上述測試用例運(yùn)行結(jié)果如下:

        === test session starts ===platform win32 — Python 3.8.1, pytest-6.2.4, py-1.10.0, pluggy-0.13.1rootdir: C:UsersyuruoDesktopmpplugins: allure-pytest-2.8.11, forked-1.3.0, rerunfailures-9.1.1, timeout-1.4.2, xdist-2.2.1collected 1 itemtest_a.yaml 123.=== 1 passed in 0.02s ====

        當(dāng)然,也支持復(fù)雜一些的測試用例:

        test_abc: – print: 123 – print: 456test_abd: – print: 123 – print: 456

        其結(jié)果如下:

        == test session starts ==platform win32 — Python 3.8.1, pytest-6.2.4, py-1.10.0, pluggy-0.13.1rootdir: C:UsersyuruoDesktopmpplugins: allure-pytest-2.8.11, forked-1.3.0, rerunfailures-9.1.1, timeout-1.4.2, xdist-2.2.1collected 2 itemstest_a.yaml 123456.123456.== 2 passed in 0.02s ==

        利用pytest創(chuàng)建數(shù)據(jù)驅(qū)動(dòng)測試框架就介紹到這里啦,希望能給大家?guī)硪欢ǖ膸椭4蠹矣惺裁床欢牡胤交蛘哂幸苫笠部梢粤粞杂懻摴?,讓我們共同進(jìn)步呦!

        重點(diǎn):學(xué)習(xí)資料學(xué)習(xí)當(dāng)然離不開資料,這里當(dāng)然也給你們準(zhǔn)備了600G的學(xué)習(xí)資料

        需要的私我關(guān)鍵字【000】免費(fèi)獲取哦 注意關(guān)鍵字是:000

        項(xiàng)目實(shí)戰(zhàn)

        app項(xiàng)目,銀行項(xiàng)目,醫(yī)藥項(xiàng)目,電商,金融

        大型電商項(xiàng)目

        全套軟件測試自動(dòng)化測試教學(xué)視頻

        300G教程資料下載【視頻教程+PPT+項(xiàng)目源碼】

        全套軟件測試自動(dòng)化測試大廠面經(jīng)

        python自動(dòng)化測試++全套模板+性能測試

        聽說關(guān)注我并三連的鐵汁都已經(jīng)升職加薪暴富了哦?。。。?/p>

        鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
        上一篇 2022年6月17日 18:04
        下一篇 2022年6月17日 18:04

        相關(guān)推薦

        聯(lián)系我們

        聯(lián)系郵箱:admin#wlmqw.com
        工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息