Pytest框架之fixture的詳細使用教程
前言
前面一篇講了setup、teardown可以實現在執行用例前或結束後加入一些操作,但這種都是針對整個指令碼全域性生效的
如果有以下場景:用例 1 需要先登入,用例 2 不需要登入,用例 3 需要先登入。很顯然無法用 setup 和 teardown 來實現了fixture可以讓我們自定義測試用例的前置條件
fixture優勢
- 命名方式靈活,不侷限於 setup 和teardown 這幾個命名
- conftest.py 配置裡可以實現資料共享,不需要 import 就能自動找到fixture
- scope="module" 可以實現多個.py 跨檔案共享前置
- scope="session" 以實現多個.py 跨檔案使用一個 session 來完成多個用例
fixture引數列表
@pytest.fixture(scope="function",params=None,autouse=False,ids=None,name=None)
def test():
print("fixture初始化的引數列表")
引數列表
- scope:可以理解成fixture的作用域,預設:function,還有class、module、package、session四個【常用】
- autouse:預設:False,需要用例手動呼叫該fixture;如果是True,所有作用域內的測試用例都會自動呼叫該fixture
- name:預設:裝飾器的名稱,同一模組的fixture相互呼叫建議寫個不同的name
注意
session的作用域:是整個測試會話,即開始執行pytest到結束測試
測試用例如何呼叫fixture
- 將fixture名稱作為測試用例函式的輸入引數
- 測試用例加上裝飾器:@pytest.mark.usefixtures(fixture_name)
- fixture設定autouse=True
#!/usr/bin/env python # -*- coding: utf-8 -*- """ __title__ = __Time__ = 2020-04-06 15:50 __Author__ = 小菠蘿測試筆記 __Blog__ = https://www.cnblogs.com/poloyy/ """ import pytest # 呼叫方式一 @pytest.fixture def login(): print("輸入賬號,密碼先登入") def test_s1(login): print("用例 1:登入之後其它動作 111") def test_s2(): # 不傳 login print("用例 2:不需要登入,操作 222") # 呼叫方式二 @pytest.fixture def login2(): print("please輸入賬號,密碼先登入") @pytest.mark.usefixtures("login2","login") def test_s11(): print("用例 11:登入之後其它動作 111") # 呼叫方式三 @pytest.fixture(autouse=True) def login3(): print("====auto===") # 不是test開頭,加了裝飾器也不會執行fixture @pytest.mark.usefixtures("login2") def loginss(): print(123)
執行結果
fixture的例項化順序
- 較高 scope 範圍的fixture(session)在較低 scope 範圍的fixture( function 、 class )之前例項化【session > package > module > class > function】
- 具有相同作用域的fixture遵循測試函式中宣告的順序,並遵循fixture之間的依賴關係【在fixture_A裡面依賴的fixture_B優先例項化,然後到fixture_A例項化】
- 自動使用(autouse=True)的fixture將在顯式使用(傳參或裝飾器)的fixture之前例項化
#!/usr/bin/env python # -*- coding: utf-8 -*- """ __title__ = __Time__ = 2020-04-06 16:14 __Author__ = 小菠蘿測試筆記 __Blog__ = https://www.cnblogs.com/poloyy/ """ import pytest order = [] @pytest.fixture(scope="session") def s1(): order.append("s1") @pytest.fixture(scope="module") def m1(): order.append("m1") @pytest.fixture def f1(f3,a1): # 先例項化f3,再例項化a1,最後例項化f1 order.append("f1") assert f3 == 123 @pytest.fixture def f3(): order.append("f3") a = 123 yield a @pytest.fixture def a1(): order.append("a1") @pytest.fixture def f2(): order.append("f2") def test_order(f1,m1,f2,s1): # m1、s1在f1後,但因為scope範圍大,所以會優先例項化 assert order == ["s1","m1","f3","a1","f1","f2"]
執行結果
斷言成功
關於fixture的注意點
添加了 @pytest.fixture
,如果fixture還想依賴其他fixture,需要用函式傳參的方式,不能用 @pytest.mark.usefixtures()
的方式,否則會不生效
@pytest.fixture(scope="session") def open(): print("===開啟瀏覽器===") @pytest.fixture # @pytest.mark.usefixtures("open") 不可取!!!不生效!!! def login(open): # 方法級別前置操作setup print(f"輸入賬號,密碼先登入{open}")
前面講的,其實都是setup的操作,那麼現在就來講下teardown是怎麼實現的
用fixture實現teardown並不是一個獨立的函式,而是用 yield 關鍵字來開啟teardown操作
#!/usr/bin/env python # -*- coding: utf-8 -*- """ __title__ = __Time__ = 2020-04-06 15:50 __Author__ = 小菠蘿測試筆記 __Blog__ = https://www.cnblogs.com/poloyy/ """ import pytest @pytest.fixture(scope="session") def open(): # 會話前置操作setup print("===開啟瀏覽器===") test = "測試變數是否返回" yield test # 會話後置操作teardown print("==關閉瀏覽器==") @pytest.fixture def login(open): # 方法級別前置操作setup print(f"輸入賬號,密碼先登入{open}") name = "==我是賬號==" pwd = "==我是密碼==" age = "==我是年齡==" # 返回變數 yield name,pwd,age # 方法級別後置操作teardown print("登入成功") def test_s1(login): print("==用例1==") # 返回的是一個元組 print(login) # 分別賦值給不同變數 name,age = login print(name,age) assert "賬號" in name assert "密碼" in pwd assert "年齡" in age def test_s2(login): print("==用例2==") print(login)
yield注意事項
- 如果yield前面的程式碼,即setup部分已經丟擲異常了,則不會執行yield後面的teardown內容
- 如果測試用例丟擲異常,yield後面的teardown內容還是會正常執行
yield+with的結合
# 官方例子 @pytest.fixture(scope="module") def smtp_connection(): with smtplib.SMTP("smtp.gmail.com",587,timeout=5) as smtp_connection: yield smtp_connection # provide the fixture value
該 smtp_connection
連線將測試完成執行後已經關閉,因為 smtp_connection
物件自動關閉時, with
語句結束。
addfinalizer 終結函式
@pytest.fixture(scope="module") def test_addfinalizer(request): # 前置操作setup print("==再次開啟瀏覽器==") test = "test_addfinalizer" def fin(): # 後置操作teardown print("==再次關閉瀏覽器==") request.addfinalizer(fin) # 返回前置操作的變數 return test def test_anthor(test_addfinalizer): print("==最新用例==",test_addfinalizer)
注意事項
如果 request.addfinalizer() 前面的程式碼,即setup部分已經丟擲異常了,則不會執行 request.addfinalizer() 的teardown內容(和yield相似,應該是最近新版本改成一致了)
可以宣告多個終結函式並呼叫
總結
到此這篇關於Pytest框架之fixture的詳細使用教程的文章就介紹到這了,更多相關Pytest fixture使用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!