pytest進(jìn)階教程之fixture函數(shù)詳解
fixture函數(shù)存在意義
與python自帶的unitest測(cè)試框架中的setup、teardown類(lèi)似,pytest提供了fixture函數(shù)用以在測(cè)試執(zhí)行前和執(zhí)行后進(jìn)行必要的準(zhǔn)備和清理工作。但是相對(duì)來(lái)說(shuō)又比setup、teardown好用。
firture相對(duì)于setup和teardown的優(yōu)勢(shì)
- 命名方式靈活,不局限于setup和teardown這幾個(gè)命名
- conftest.py 配置里可以實(shí)現(xiàn)數(shù)據(jù)共享,不需要import就能自動(dòng)找到一些配置
- scope="module" 可以實(shí)現(xiàn)多個(gè).py跨文件共享前置, 每一個(gè).py文件調(diào)用一次
- scope="session" 以實(shí)現(xiàn)多個(gè).py跨文件使用一個(gè)session來(lái)完成多個(gè)用例
fixture函數(shù)定義
通過(guò)將fixture聲明為參數(shù)名,測(cè)試用例函數(shù)可以請(qǐng)求fixture。fixture修飾器來(lái)標(biāo)記固定的工廠函數(shù),在其他函數(shù),模塊,類(lèi)或整個(gè)工程調(diào)用它時(shí)會(huì)被激活并優(yōu)先執(zhí)行,通常會(huì)被用于完成預(yù)置處理和重復(fù)操作。
# 定義的夾具函數(shù),使用裝飾器pytest.fixture @pytest.fixture def my_fruit(): print("login:用戶(hù)執(zhí)行登錄操作") # 使用夾具函數(shù)的測(cè)試用例 def test_my_fruit_in_basket(my_fruit): print("hello world") if __name__ == '__main__': pytest.main(['test_login.py::test_my_fruit_in_basket', '-s']) #執(zhí)行結(jié)果: collected 1 item test_login.py login: 用戶(hù)執(zhí)行登錄操作 hello world . ============================== 1 passed in 0.02s ==========================
fixture作用
- 做測(cè)試前后的初始化設(shè)置,如測(cè)試數(shù)據(jù)準(zhǔn)備,鏈接數(shù)據(jù)庫(kù),打開(kāi)瀏覽器等這些操作都可以使用fixture來(lái)實(shí)現(xiàn)。
- 測(cè)試用例的前置條件可以使用fixture實(shí)現(xiàn) 。
- 支持經(jīng)典的xunit fixture ,像unittest使用的setup和teardown。
- fixture可以實(shí)現(xiàn)unittest不能實(shí)現(xiàn)的功能,比如unittest中的測(cè)試用例和測(cè)試用例之間是無(wú)法傳遞參數(shù)和數(shù)據(jù)的,但是fixture卻可以解決這個(gè)問(wèn)題。
調(diào)用fixture有三種方式
Fixture名字作為測(cè)試用例的參數(shù)
可以直接使用fixture名稱(chēng)作為輸入?yún)?shù)(是個(gè)典型的高階函數(shù)),在這種情況下,fixture函數(shù)返回的fixture實(shí)例將被注入,最終在測(cè)試用例執(zhí)行前執(zhí)行這個(gè)裝飾過(guò)的函數(shù)。如下列代碼,①將返回值傳遞給測(cè)試用例,②通過(guò)函數(shù)入?yún)⒎绞剑梢詡魅攵鄠€(gè)fixture函數(shù)
import pytest @pytest.fixture def first_entry(): return "a" @pytest.fixture def order(first_entry): return [first_entry] def test_string(order): order.append("b") assert order == ["a", "b"], "斷言執(zhí)行失敗" if __name__ == '__main__': pytest.main(['test_login.py::test_string', '-s'])
使用@pytest.mark.usefixtures('fixture')裝飾器
每個(gè)函數(shù)或者類(lèi)前使用@pytest.mark.usefixtures('fixture')裝飾器進(jìn)行裝飾。
import pytest @pytest.fixture def my_fruit(): print("login:用戶(hù)執(zhí)行登錄操作") # 被夾具函數(shù)裝飾的測(cè)試用例 @pytest.mark.usefixtures("my_fruit") def test_my_fruit_in_basket(): print("hello world") if __name__ == '__main__': pytest.main(['test_login.py', '-s', '-q']) # 執(zhí)行結(jié)果 login:用戶(hù)執(zhí)行登錄操作 hello world . 1 passed in 0.01s
使用autouse參數(shù)
指定fixture的參數(shù)autouse=True這樣模塊內(nèi)的每個(gè)測(cè)試用例會(huì)自動(dòng)調(diào)用fixture。
import pytest @pytest.fixture(autouse=True) def my_fruit(): print("login:用戶(hù)執(zhí)行登錄操作") # 被夾具函數(shù)裝飾的測(cè)試用例 def test_my_fruit_in_basket(): print("hello world") if __name__ == '__main__': pytest.main(['test_login.py', '-s', '-q'])
備注: 如果fixture有返回值,那么usefixture以及autouse就無(wú)法獲取到返回值,這個(gè)是裝飾器usefixture與用例直接傳fixture參數(shù)的區(qū)別。 因此最常用的是通過(guò)參數(shù)傳遞的方法。
指定Fixture函數(shù)的作用范圍
Fixture中的scope的參數(shù),控制Fixture函數(shù)的作用范圍
scope = ‘function' 測(cè)試函數(shù)維度,默認(rèn)范圍,則在測(cè)試結(jié)束時(shí)銷(xiāo)毀fixture。
scope = ‘class' 測(cè)試類(lèi)維度,在class中最后一次測(cè)試的拆卸過(guò)程中,夾具被破壞。
scope = ‘module' 測(cè)試文件維度,在模塊中最后一次測(cè)試的拆卸過(guò)程中,夾具被破壞。
scope = ‘session' 測(cè)試會(huì)話維度,夾具在測(cè)試會(huì)話結(jié)束時(shí)被銷(xiāo)毀。
fixture函數(shù)的返回值:return 和 yield 和 addfinalizer終結(jié)函數(shù)
return:
通過(guò)下面的代碼,我們已經(jīng)發(fā)現(xiàn)可以通過(guò)測(cè)試用例函數(shù)傳入?yún)?shù)的形式,直接使用fixture函數(shù)的返回值,這個(gè)相對(duì)來(lái)說(shuō)比較簡(jiǎn)單。
import pytest @pytest.fixture def first_entry(): return "a" @pytest.fixture def order(first_entry): return [first_entry] def test_string(order): order.append("b") assert order == ["a", "b"], "斷言執(zhí)行失敗" if __name__ == '__main__': pytest.main(['test_login.py::test_string', '-s'])
yield:
yeild也是一種函數(shù)的返回值類(lèi)型,是函數(shù)上下文管理器,使用yield被調(diào)fixture函數(shù)執(zhí)行遇到y(tǒng)ield會(huì)停止執(zhí)行,接著執(zhí)行調(diào)用的函數(shù),調(diào)用的函數(shù)執(zhí)行完后會(huì)繼續(xù)執(zhí)行fixture函數(shù)yield關(guān)鍵后面的代碼。因此利用fixture函數(shù),我們可以說(shuō)pytest集合了setup、teardown,既做了初始化,又做了后置的清理工作。
import pytest from emaillib import Email, MailAdminClient @pytest.fixture def mail_admin(): return MailAdminClient() # 配置發(fā)送者的fixture函數(shù) @pytest.fixture def sending_user(mail_admin): user = mail_admin.create_user() #setup:創(chuàng)建發(fā)件人 yield user # 返回發(fā)件人 admin_client.delete_user(user) #teardown:刪除發(fā)件人 # 配置收件人的fixture函數(shù) @pytest.fixture def receiving_user(mail_admin): user = mail_admin.create_user() #setup:創(chuàng)建收件人 yield user #返回收件人 admin_client.delete_user(user) #teardown:刪除收件人 def test_email_received(sending_user, receiving_user, email): email = Email(subject="Hey!", body="How's it going?") sending_user.send_email(email, receiving_user) assert email in receiving_user.inbox
項(xiàng)目中的實(shí)際使用
翻譯下面代碼,在調(diào)用Entry_into_index前,啟動(dòng)APP,遇到y(tǒng)ield關(guān)鍵字,中止fixture函數(shù)調(diào)用,執(zhí)行調(diào)用函數(shù)Entry_into_index內(nèi)容,在Entry_into_index函數(shù)調(diào)用后,執(zhí)行yield函數(shù)后的driver.close_app(),關(guān)閉APP。
@pytest.fixture(scope='session') def startApp_fixture(start_app): driver = start_app res = lp(driver).get_agree_info() try: assert res == "同意" except Exception as e: log.error("啟動(dòng)APP失敗") log.exception(e) raise e else: lp(driver).click_agree() lp(driver).click_next_step() lp(driver).click_alert() lp(driver).click_pass() # 創(chuàng)建首頁(yè) index_page = indexPage(driver) yield index_page, driver # 后置條件 time.sleep(3) driver.close_app() # 調(diào)用fixture函數(shù) @pytest.fixture(scope='session') def Entry_into_index(startApp_fixture) index_page = startApp_fixture()[0] driver = startApp_fixture()[1]
fixture函數(shù)需要傳遞參數(shù)
工廠作為固定裝置:可以使用閉包,通過(guò)外部去調(diào)用函數(shù)里面函數(shù)。
工廠固定裝置原因:
上面已經(jīng)說(shuō)過(guò),調(diào)用fixture函數(shù)A可以通過(guò)用fixture名稱(chēng)作為調(diào)用函數(shù)B參數(shù),在這種情況下,fixture函數(shù)返回的fixture實(shí)例將被注入,最終在測(cè)試用例B執(zhí)行前執(zhí)行這個(gè)裝飾過(guò)的函數(shù)def B(A):pass。但是有個(gè)問(wèn)題在給測(cè)試用例添加裝飾函數(shù)時(shí),傳入的參數(shù)是fixture函數(shù)的函數(shù)名,如果需要給fixture函數(shù)添加參數(shù)時(shí),是不可以用下面形式,代碼會(huì)直接報(bào)錯(cuò)。原因是測(cè)試用例傳入?yún)?shù)為fixture函數(shù)名,如果fixture函數(shù)名添加(參數(shù))后,表現(xiàn)形式為add(params)實(shí)際為函數(shù)調(diào)用??蓞⒖几唠A函數(shù)與裝飾器,并無(wú)此用法。
解決方式使用閉包,如下圖代碼:make_customer_record函數(shù)返回的是內(nèi)部函數(shù)_make_customer_record(夾具不直接返回?cái)?shù)據(jù),而是返回一個(gè)生成數(shù)據(jù)的函數(shù)),注意此處未加(),非函數(shù)調(diào)用,因此在測(cè)試用例中customer_1 = make_customer_record("Lisa")此處可拆解為兩部分,customer_1 = make_customer_record的結(jié)果為_(kāi)make_customer_record對(duì)象 ,加上("Lisa") 實(shí)際是對(duì)調(diào)_make_customer_record函數(shù)進(jìn)行調(diào)用:函數(shù)名+(參數(shù)),以達(dá)到可以傳參的目的。
@pytest.fixture def make_customer_record(): def _make_customer_record(name): return {"name": name, "orders": []} return _make_customer_record #注意此處不加(),非函數(shù)調(diào)用 def test_customer_records(make_customer_record): customer_1 = make_customer_record("Lisa")
總結(jié)
到此這篇關(guān)于pytest進(jìn)階教程之fixture函數(shù)的文章就介紹到這了,更多相關(guān)pytest fixture函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- pytest官方文檔解讀fixtures的調(diào)用方式
- pytest官方文檔解讀fixtures
- pytest解讀fixture有效性及跨文件共享fixtures
- pytest?fixtures函數(shù)及測(cè)試函數(shù)的參數(shù)化解讀
- 分享Pytest fixture參數(shù)傳遞的幾種方式
- pytest自動(dòng)化測(cè)試中的fixture的聲明和調(diào)用
- pytest框架之fixture詳細(xì)使用詳解
- Pytest框架之fixture的詳細(xì)使用教程
- python pytest進(jìn)階之xunit fixture詳解
- python pytest進(jìn)階之fixture詳解
- Pytest框架之fixture詳解(一)
相關(guān)文章
Python Barbershop實(shí)現(xiàn)照片換發(fā)型功能
這篇文章主要為大家介紹了一個(gè)開(kāi)源項(xiàng)目(Barbershop),可以將照片中的發(fā)型更換成另一個(gè),文中實(shí)現(xiàn)過(guò)程講解詳細(xì),感興趣的可以學(xué)習(xí)一下2022-01-01Python學(xué)習(xí)之函數(shù)的定義與使用詳解
函數(shù)是具有某種特定功能的代碼塊,可以重復(fù)使用(在前面數(shù)據(jù)類(lèi)型相關(guān)章節(jié)。它使得我們的程序更加模塊化,不需要編寫(xiě)大量重復(fù)的代碼。本文將詳細(xì)介紹Python中函數(shù)的定義與使用,感興趣的可以學(xué)習(xí)一下2022-03-03python實(shí)現(xiàn)幾種歸一化方法(Normalization Method)
這篇文章主要介紹了python實(shí)現(xiàn)幾種歸一化方法(Normalization Method),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07python 3.0 模擬用戶(hù)登錄功能并實(shí)現(xiàn)三次錯(cuò)誤鎖定
Python的3.0版本,常被稱(chēng)為Python 3000,或簡(jiǎn)稱(chēng)Py3k。這篇文章主要介紹了python 3.0 模擬用戶(hù)登錄功能并實(shí)現(xiàn)三次錯(cuò)誤鎖定,需要的朋友可以參考下2017-11-11Flask如何獲取用戶(hù)的ip,查詢(xún)用戶(hù)的登錄次數(shù),并且封ip
這篇文章主要介紹了Flask如何獲取用戶(hù)的ip,查詢(xún)用戶(hù)的登錄次數(shù),并且封ip問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01一個(gè)入門(mén)級(jí)python爬蟲(chóng)教程詳解
這篇文章主要介紹了一個(gè)入門(mén)級(jí)python爬蟲(chóng)教程詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01PyTorch快速搭建神經(jīng)網(wǎng)絡(luò)及其保存提取方法詳解
本篇文章主要介紹了PyTorch快速搭建神經(jīng)網(wǎng)絡(luò)及其保存提取方法詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04使用Python對(duì)網(wǎng)易云歌單數(shù)據(jù)分析及可視化
這篇文章主要介紹了使用Python對(duì)網(wǎng)易云歌單數(shù)據(jù)分析及可視化,本項(xiàng)目以數(shù)據(jù)采集、處理、分析及數(shù)據(jù)可視化為項(xiàng)目流程,需要的朋友可以參考下2023-03-03