fixture函數(shù)存在意義
與python自帶的unitest測試框架中的setup、teardown類似,pytest提供了fixture函數(shù)用以在測試執(zhí)行前和執(zhí)行后進行必要的準備和清理工作。但是相對來說又比setup、teardown好用。
firture相對于setup和teardown的優(yōu)勢
- 命名方式靈活,不局限于setup和teardown這幾個命名
- conftest.py 配置里可以實現(xiàn)數(shù)據(jù)共享,不需要import就能自動找到一些配置
- scope="module" 可以實現(xiàn)多個.py跨文件共享前置, 每一個.py文件調用一次
- scope="session" 以實現(xiàn)多個.py跨文件使用一個session來完成多個用例
fixture函數(shù)定義
通過將fixture聲明為參數(shù)名,測試用例函數(shù)可以請求fixture。fixture修飾器來標記固定的工廠函數(shù),在其他函數(shù),模塊,類或整個工程調用它時會被激活并優(yōu)先執(zhí)行,通常會被用于完成預置處理和重復操作。
# 定義的夾具函數(shù),使用裝飾器pytest.fixture
@pytest.fixture
def my_fruit():
print("login:用戶執(zhí)行登錄操作")
# 使用夾具函數(shù)的測試用例
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í)行結果:
collected 1 item
test_login.py login:
用戶執(zhí)行登錄操作
hello world
.
============================== 1 passed in 0.02s ==========================
fixture作用
- 做測試前后的初始化設置,如測試數(shù)據(jù)準備,鏈接數(shù)據(jù)庫,打開瀏覽器等這些操作都可以使用fixture來實現(xiàn)。
- 測試用例的前置條件可以使用fixture實現(xiàn) 。
- 支持經(jīng)典的xunit fixture ,像unittest使用的setup和teardown。
- fixture可以實現(xiàn)unittest不能實現(xiàn)的功能,比如unittest中的測試用例和測試用例之間是無法傳遞參數(shù)和數(shù)據(jù)的,但是fixture卻可以解決這個問題。
調用fixture有三種方式
Fixture名字作為測試用例的參數(shù)
可以直接使用fixture名稱作為輸入?yún)?shù)(是個典型的高階函數(shù)),在這種情況下,fixture函數(shù)返回的fixture實例將被注入,最終在測試用例執(zhí)行前執(zhí)行這個裝飾過的函數(shù)。如下列代碼,①將返回值傳遞給測試用例,②通過函數(shù)入?yún)⒎绞?,可以傳入多個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')裝飾器
每個函數(shù)或者類前使用@pytest.mark.usefixtures('fixture')裝飾器進行裝飾。
import pytest
@pytest.fixture
def my_fruit():
print("login:用戶執(zhí)行登錄操作")
# 被夾具函數(shù)裝飾的測試用例
@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í)行結果
login:用戶執(zhí)行登錄操作
hello world
.
1 passed in 0.01s
使用autouse參數(shù)
指定fixture的參數(shù)autouse=True這樣模塊內的每個測試用例會自動調用fixture。
import pytest
@pytest.fixture(autouse=True)
def my_fruit():
print("login:用戶執(zhí)行登錄操作")
# 被夾具函數(shù)裝飾的測試用例
def test_my_fruit_in_basket():
print("hello world")
if __name__ == '__main__':
pytest.main(['test_login.py', '-s', '-q'])
備注: 如果fixture有返回值,那么usefixture以及autouse就無法獲取到返回值,這個是裝飾器usefixture與用例直接傳fixture參數(shù)的區(qū)別。 因此最常用的是通過參數(shù)傳遞的方法。
指定Fixture函數(shù)的作用范圍
Fixture中的scope的參數(shù),控制Fixture函數(shù)的作用范圍
scope = ‘function' 測試函數(shù)維度,默認范圍,則在測試結束時銷毀fixture。
scope = ‘class' 測試類維度,在class中最后一次測試的拆卸過程中,夾具被破壞。
scope = ‘module' 測試文件維度,在模塊中最后一次測試的拆卸過程中,夾具被破壞。
scope = ‘session' 測試會話維度,夾具在測試會話結束時被銷毀。
fixture函數(shù)的返回值:return 和 yield 和 addfinalizer終結函數(shù)
return:
通過下面的代碼,我們已經(jīng)發(fā)現(xiàn)可以通過測試用例函數(shù)傳入?yún)?shù)的形式,直接使用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'])
yield:
yeild也是一種函數(shù)的返回值類型,是函數(shù)上下文管理器,使用yield被調fixture函數(shù)執(zhí)行遇到y(tǒng)ield會停止執(zhí)行,接著執(zhí)行調用的函數(shù),調用的函數(shù)執(zhí)行完后會繼續(xù)執(zhí)行fixture函數(shù)yield關鍵后面的代碼。因此利用fixture函數(shù),我們可以說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
項目中的實際使用
翻譯下面代碼,在調用Entry_into_index前,啟動APP,遇到y(tǒng)ield關鍵字,中止fixture函數(shù)調用,執(zhí)行調用函數(shù)Entry_into_index內容,在Entry_into_index函數(shù)調用后,執(zhí)行yield函數(shù)后的driver.close_app(),關閉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("啟動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)建首頁
index_page = indexPage(driver)
yield index_page, driver
# 后置條件
time.sleep(3)
driver.close_app()
# 調用fixture函數(shù)
@pytest.fixture(scope='session')
def Entry_into_index(startApp_fixture)
index_page = startApp_fixture()[0]
driver = startApp_fixture()[1]
fixture函數(shù)需要傳遞參數(shù)
工廠作為固定裝置:可以使用閉包,通過外部去調用函數(shù)里面函數(shù)。
工廠固定裝置原因:
上面已經(jīng)說過,調用fixture函數(shù)A可以通過用fixture名稱作為調用函數(shù)B參數(shù),在這種情況下,fixture函數(shù)返回的fixture實例將被注入,最終在測試用例B執(zhí)行前執(zhí)行這個裝飾過的函數(shù)def B(A):pass。但是有個問題在給測試用例添加裝飾函數(shù)時,傳入的參數(shù)是fixture函數(shù)的函數(shù)名,如果需要給fixture函數(shù)添加參數(shù)時,是不可以用下面形式,代碼會直接報錯。原因是測試用例傳入?yún)?shù)為fixture函數(shù)名,如果fixture函數(shù)名添加(參數(shù))后,表現(xiàn)形式為add(params)實際為函數(shù)調用??蓞⒖几唠A函數(shù)與裝飾器,并無此用法。

解決方式使用閉包,如下圖代碼:make_customer_record函數(shù)返回的是內部函數(shù)_make_customer_record(夾具不直接返回數(shù)據(jù),而是返回一個生成數(shù)據(jù)的函數(shù)),注意此處未加(),非函數(shù)調用,因此在測試用例中customer_1 = make_customer_record("Lisa")此處可拆解為兩部分,customer_1 = make_customer_record的結果為_make_customer_record對象 ,加上("Lisa") 實際是對調_make_customer_record函數(shù)進行調用:函數(shù)名+(參數(shù)),以達到可以傳參的目的。
@pytest.fixture
def make_customer_record():
def _make_customer_record(name):
return {"name": name, "orders": []}
return _make_customer_record #注意此處不加(),非函數(shù)調用
def test_customer_records(make_customer_record):
customer_1 = make_customer_record("Lisa")
總結
到此這篇關于pytest進階教程之fixture函數(shù)的文章就介紹到這了,更多相關pytest fixture函數(shù)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- pytest框架之fixture詳細使用詳解
- python pytest進階之fixture詳解
- Python 測試框架unittest和pytest的優(yōu)劣
- Python自動化測試pytest中fixtureAPI簡單說明