pytest中fixture函數使用
前言
setup和teardown能實現在測試用例執(zhí)行之前或之后做一些操作,但是這種是整個測試腳本全局生效的;
如果我們想實現某些用例執(zhí)行之前進行登錄,某些用例執(zhí)行之前不需要進行登錄,這種場景我們再使用setup和teardown就無法實現了,這時候我們就需要用到fixture功能了。
fixture函數
fixture(scope="function", params=None, autouse=False, ids=None, name=None)
參數說明:
1、scope:fixture函數的作用域;可選值:function(默認)、class、module、session
- function:作用于每個方法或函數,每個方法或函數都運行一次
- class:作用于整個class類,每個class中的所有test只運行一次
- module:作用于整個模塊,每個module中的所有test只運行一次
- session:作用于整個session,整個session只運行一次(慎用)
2、params:列表類型;一個可選的參數列表;它將會多次調用被fixture標記的方法和所有用到這個fixture的test測試用例;默認為None;當前調用參數可以用 request.param 來獲取。
3、autouse:如果為True,則為所有測試用例激活fixture,運行測試用例的時候會自動運行被fixture標記的方法;如果為False,則需要顯示指定來激活fixture,不會自動運行。
4、ids:id字符串列表,與params相對應,因此它們也是測試的一部分。如果沒有提供ids,那么將會從params來自動生成。
5、name:fixture的名稱。默認為被fixture裝飾器標記的函數名。
fixture的使用
1、通過參數引用fixture函數
舉例:
# file_name:test_fixture.py
import pytest
class Test_A:
@pytest.fixture()
def before(self):
print("\n--------before fixture has ran--------")
def test_a(self, before): # test_a方法以參數的形式傳入了被fixture標記的函數,fixture的名稱默認為被fixture標記的函數名
print('-------test_a has ran-------')
assert 1
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])運行結果:

從結果中可以看到被fixture標記的函數before會優(yōu)先于測試用例test_a運行。
2、通過使用name參數來引用fixture函數
①name參數表示fixture的重命名;
②通常來說使用 fixture 的測試函數會將 fixture 的函數名作為參數傳遞,但是 pytest 也允許將fixture重命名。
舉例1:
# file_name:test_fixture.py
import pytest
class Test_A:
@pytest.fixture(name="before_fixture_name")
def before(self):
print("\n--------before fixture has ran--------")
def test_a(self, before_fixture_name): # test_a方法以參數的形式傳入了被fixture標記的函數,這里的fixture名稱為:before_fixture_name,如果不設置name參數,則fixture的名稱默認為被fixture標記的函數名
print('-------test_a has ran-------')
assert 1
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])舉例2:為fixture函數重命名之后,不可以在使用fixture函數的函數名來調用,只能通過fixture函數重命名的新名字來調用。

3、通過@pytest.mark.usefixtures('fixture函數名')函數的形式引用fixture函數
舉例:
# file_name: test_fixture.py
import pytest
@pytest.fixture() # 被fixture標記的函數也可以應用在測試類的外部,使用@pytest.mark.usefixtures()裝飾器來引用
def before():
print("\n--------before fixture has ran--------")
@pytest.mark.usefixtures("before") # 通過使用usefixtures()來引用fixture,此時usefixtures()函數的入參是fixture函數的函數名
class Test_A:
def test_a(self):
print('-------test_a has ran-------')
assert 1
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])運行結果:

從結果中可以看到被fixture標記的函數before會優(yōu)先于測試用例test_a運行。
4、通過autouse=True設置默認執(zhí)行fixture函數
①fixture函數的autouse參數默認等于False;
②fixture函數的autouse參數若為True,剛每個測試函數都會自動調用該fixture函數,而且無需傳入fixture函數名。
舉例:
# file_name: test_fixture.py
import pytest
@pytest.fixture(autouse=True) # 通過參數autouse=True來設置fixture默認運行
def before():
print("\n--------before fixture has ran--------")
class Test_A:
def test_a(self):
print('-------test_a has ran-------')
assert 1
def test_b(self):
print('-------test_b has ran-------')
assert 1
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])運行結果:

從結果中可以看到我們并沒有顯示指定test_a和test_b使用fixture,但是在執(zhí)行測試用例之前卻執(zhí)行了fixture,這就是因為我們將fixture設置成了autouse=True。
5、fixture作用域設置成function
舉例:
# file_name: test_fixture.py
import pytest
@pytest.fixture(scope="function", autouse=True) # 作用域設置成function,通過參數autouse=True來設置fixture默認運行
def before():
print("\n--------before fixture has ran--------")
class Test_A:
def test_a(self):
print('-------test_a has ran-------')
assert 1
def test_b(self):
print('-------test_b has ran-------')
assert 1
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])運行結果:

從結果中可以看到將fixture的作用域設置成scope=function后,每個test測試用例執(zhí)行前都會執(zhí)行一次被fixture標記的函數。
并且通過跟上一個例子對比我們可以看到設置 scope=function 和不設置scope參數的執(zhí)行結果是一致的,這說明scope參數的默認值是function。
6、fixture作用域設置成class
舉例:
# file_name: test_fixture.py
import pytest
@pytest.fixture(scope="class", autouse=True) # 作用域設置成class,通過參數autouse=True來設置fixture默認運行
def before():
print("\n--------before fixture has ran--------")
class Test_A:
def test_a(self):
print('-------test_a has ran-------')
assert 1
def test_b(self):
print('-------test_b has ran-------')
assert 1
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])運行結果:

從運行結果中可以看到測試類中有兩個測試用例,但是fixture卻只執(zhí)行了一次。
7、fixture的返回值使用
舉例:
# file_name: test_fixture.py
import pytest
@pytest.fixture()
def return_data():
print("\n--------before fixture has ran--------")
return 2 # 返回值
class Test_A:
def test_a(self, return_data):
print('-------test_a has ran-------')
assert 1 == return_data # 拿到返回值做斷言
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])運行結果:

從結果中看到我們拿到了fixture的返回值為2,在測試用例中拿到返回值做斷言,斷言失敗。
8、fixture的params參數使用
①params形參是fixture函數的可選形參列表,支持列表傳入;
②不傳此參數時默認為None;
③每個param的值fixture函數都會去調用執(zhí)行一次,類似for循環(huán)。
④可與參數ids一起使用,作為每個參數的標識,類似于用例參數化時的ids作用。
舉例:
# file_name: test_fixture.py
import pytest
@pytest.fixture(params=[1, 2, 3])
def return_data(request): # 傳入參數request,request系統(tǒng)內置的fixture
print("\n--------before fixture has ran--------")
return request.param # 通過request.param 獲取當前傳入的參數
class Test_A:
def test_a(self, return_data):
print('-------test_a has ran,return_data的值為:{}-------'.format(return_data))
assert 1 == return_data # 拿到返回值做斷言
if __name__ == '__main__':
pytest.main(['-s', 'test_fixture.py'])運行結果:

從結果中我們可以看到測試用例執(zhí)行了3次。通過設置params參數會導致多次調用被fixture標記的函數,并且使用該fixture函數的測試用例也會執(zhí)行多次。

9、fixture的params參數于ids參數結合使用
①fixture函數未配置ids參數之前:用例執(zhí)行后的標識為傳入的params參數。

②fixture函數配置ids參數之后:用例執(zhí)行后的標識為傳入的ids參數。并與params參數一一對應。

10、fixture函數的相互調用(fixture函數與fixture函數之間的依賴關系)
舉例1:
import pytest
# fixtrue作為參數,互相調用傳入
@pytest.fixture()
def account():
a = "account"
print("第一層fixture")
return a
#Fixture的相互調用一定是要在測試類里調用這層fixture才會生次,普通函數單獨調用是不生效的
@pytest.fixture()
def login(account):
print("第二層fixture")
class TestLogin:
def test_1(self, login):
print("直接使用第二層fixture,返回值為{}".format(login))
def test_2(self, account):
print("只調用account fixture,返回值為{}".format(account))
if __name__ == '__main__':
pytest.main()運行結果1:

舉例2:如果一個fixture函數依賴另外一個fixture函數,此時不能使@pytest.mark.usefixtures() 調用被依賴的fixture函數,這種調用方式不會生效。而是需要用函數傳遞的方式才能生效。
# test_fixture_02.py
import pytest
@pytest.fixture()
def login_weibo():
print("==============登陸微博===============")
@pytest.fixture()
# @pytest.mark.usefixtures("login_weibo") #這種方式不會生效
def get_weibo_data(login_weibo): # 這種方式才會生效
"""fixture函數依賴,需要用傳遞函數的方式"""
print("=============獲取微博數據==============")
@pytest.mark.demo
class TestMyCode:
@pytest.mark.usefixtures("get_weibo_data")
def test_fixture_005(self):
"""fixture函數在測試腳本文件中"""
assert 1 == 1運行結果:

【注意】
①即使fixture函數之間支持相互調用,但普通函數直接使用fixture是不支持的,一定是在測試函數內調用才會逐級調用生效。
②有多層fixture函數調用時,最先執(zhí)行的是最后一層fixture函數,而不是先執(zhí)行傳入測試函數的fixture函數。
③上層fixture函數的值不會自動return,這里就類似函數相互調用一樣的邏輯?!竞瘮嫡{用值需要賦值給一個變量并使用】
到此這篇關于pytest中fixture函數使用的文章就介紹到這了,更多相關pytest fixture函數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python編程快速上手——Excel表格創(chuàng)建乘法表案例分析
這篇文章主要介紹了Python Excel表格創(chuàng)建乘法表,結合具體實例形式分析了Python接受cmd命令操作Excel文件創(chuàng)建乘法表相關實現技巧,需要的朋友可以參考下2020-02-02

