pytest-fixture簡介及其用法講解
什么是fixture
在一個測試過程中,fixture主要提供以下功能:
為測試提供上下文,比如環(huán)境變量,數(shù)據(jù)集(dataset),提供數(shù)據(jù),數(shù)據(jù)和測試用例分開定義測試的步驟,主要用于setup和teardown
pytest中的代碼可以定制,滿足多變的測試需求,包括定義傳入測試中的數(shù)據(jù)集、配置測試前系統(tǒng)的初始狀態(tài)、為批量測試提供數(shù)據(jù)源 fixture定義
使用裝飾器 @pytest.fixture就表明這個函數(shù)是一個fixture
一個完整的fixture,定義如下:
@pytest.fixture(scope, params, autouse, ids, name)
如何使用fixture
最基本的用法就是一個fixture作為一個測試用例的參數(shù)傳入,然后就可以在該測試用例中使用該fixture
當(dāng)pytest執(zhí)行一個測試用例時,就會檢查參數(shù),然后搜索是否有相同名字的fixture,如果有,就先執(zhí)行這個fixture,得到fixture的返回值,然后將這個返回值作為參數(shù)傳入到測試用例中
一個簡單的fixture使用
import pytest class Fruit(): def __init__(self,name): self.name=name self.cubed=False def cube(self): self.cubed=True class FruitSalad(): def __init__(self,*fruit_bowl): self.fruit=fruit_bowl self._cube_fruit() def _cube_fruit(self): for fruit in self.fruit: fruit.cube() @pytest.fixture() def fruit_bowl(): return [Fruit("apple"),Fruit("banana")] def test_fruit_salad(fruit_bowl): fruit_salad=FruitSalad(*fruit_bowl) assert all(fruit.cubed for fruit in fruit_salad.fruit)
如果不使用fixture功能,代碼需要這樣寫,這樣就無法使用pytest來執(zhí)行測試用例了
class Fruit(): def __init__(self,name): self.name=name self.cubed=False def cube(self): self.cubed=True class FruitSalad(): def __init__(self,*fruit_bowl): self.fruit=fruit_bowl self._cube_fruit() def _cube_fruit(self): for fruit in self.fruit: fruit.cube() def fruit_bowl(): return [Fruit("apple"),Fruit("banana")] def test_fruit_salad(fruit_bowl): fruit_salad=FruitSalad(*fruit_bowl) assert all(fruit.cubed for fruit in fruit_salad.fruit) bowl = fruit_bowl() test_fruit_salad(fruit_bowl=bowl)
使用fixture傳遞測試數(shù)據(jù)
fixture非常適合存放測試數(shù)據(jù),并且它可以返回任何數(shù)據(jù)
import pytest @pytest.fixture() def a_tuple(): return (1,'foo',None,{'bar':23}) def test_a_tuple(a_tuple): assert a_tuple[3]["bar"]==32
a_tuple作為一個fixture,主要是提供測試數(shù)據(jù)給test_a_tuple,執(zhí)行test_a_tuple時,先查看函數(shù)的參數(shù),有a_tuple,并且找到了這個函數(shù),先執(zhí)行a_tuple,得到數(shù)據(jù)(1,‘foo’,None,{‘bar’:23}),并將這個數(shù)據(jù)傳入到測試用例test_a_tuple中,在測試用例中,就可以直接使用a_tuple來使用這個測試數(shù)據(jù)
使用fixture來執(zhí)行配置和銷毀邏輯
fixture的另一個功能就是結(jié)合yield來配置測試用例的setup和teardown邏輯
import pytest @pytest.fixture() def task_db(): print("start to setup....") yield "a" print("start to teardown...") def test_db(task_db): print(task_db) print("start to test")
運行結(jié)果:
start to setup....
a
start to test
start to teardown..
fixture函數(shù)會在測試函數(shù)之前運行,但如果fixture函數(shù)包含yield,那么系統(tǒng)會在yield處停止,轉(zhuǎn)而運行測試函數(shù),等測試函數(shù)執(zhí)行完畢后再回到fixture,繼續(xù)執(zhí)行yield后面的代碼,因此,可以將yield之前的代碼視為配置過程(setup),將yield之后的代碼視為清理過程(teardown),無論測試過程中發(fā)生了什么,yield之后的代碼都會執(zhí)行,yield可以返回值,也可以不返回
fixture可以使用其他的fixture
import pytest @pytest.fixture() def first_entry(): return "a" @pytest.fixture() def order(first_entry): return [first_entry] def test_order(order): order.append("b") assert order==["a","b"]
同時使用多個fixture
一個測試用例或者一個fixture可以同時使用多個fixture
import pytest @pytest.fixture() def first_entry(): return "a" @pytest.fixture() def second_entry(): return 2 @pytest.fixture() def order(first_entry,second_entry): return [first_entry,second_entry] @pytest.fixture() def expect_list(): return ["a",2,3.0] def test_order(order,expect_list): order.append(3.0) assert order==expect_list
fixture的參數(shù)介紹
scope,指定fixture的作用范圍
用于控制fixture執(zhí)行的配置和銷毀邏輯的頻率
scope參數(shù)有四個值:function,class,module,session
默認(rèn)值為function
function:函數(shù)級別的fixture每個測試函數(shù)只需要運行一次,
class:類級別的fixture每個測試類只運行一次
module:模塊級別的fixture,每個模塊只需要運行一次
session:繪畫級別的fixture,每次會話只需要運行一次
params,fixture的參化
params是一個list,這個list是要傳入fixture的參數(shù),會引起多次調(diào)用,request.param可以獲取每一個值
import pytest @pytest.fixture(params=["a","b"]) def order(request): return request.param def test_order(order): all_order="ab" assert order in all_order
運行結(jié)果:
collected 2 items
test_usefixture7.py::test_order[a] PASSED
test_usefixture7.py::test_order[b] PASSED
request是python的一個內(nèi)置的fixture,代表fixture的調(diào)用狀態(tài),它有一個param字段,會被@pytest.fixture(params=[“a”,“b”])的params列表中的一個元素填充,如果params有多個值,就會多次調(diào)用requeat.param來多次執(zhí)行測試用例
autouse,為常用的fixture添加autouse選項
對于常用的fixture,可以指定autouse=True,使作用域內(nèi)的測試函數(shù)都自動運行該fixture
name,為fixture重命名
import pytest @pytest.fixture(name="lue") def a_b_c_d_e(): return "a" def test_order(lue): assert lue=="a" import pytest @pytest.fixture(name="lue") def a_b_c_d_e(): return "a" def test_order(lue): assert lue=="a"
PS:
下面來說下pytest中的fixture參數(shù)解析以及用法
當(dāng)我們在使用pytest實現(xiàn)前后置調(diào)用時有兩種方式
方式一:
采用setup/teardown以及setup_class/teardown_class類似這種方式去實現(xiàn)前后置調(diào)用
方式二:
采用pytest中強大的fixture裝飾器來實現(xiàn)
本期文章主要采用方式二來解決測試用例前后置調(diào)用的問題
首先我們來看下,pytest中的fixture的參數(shù)有哪些,分別是scope,params,autouse,ids,name這5個形參,哪些他們分別的作用域以及作用是什么呢?
下面來說下scope:
“”“ scope: function(默認(rèn)) class module session params: 參數(shù)化,支持list,tuple,字典列表,字典元組 autouse: false(默認(rèn)) True ids: 當(dāng)使用params參數(shù)化時,給每一個值設(shè)置一個變量名,其實意義不大 name: 表示的是被@pytest.fixture標(biāo)記的方法取一個別名,注意:當(dāng)去了別名之后,原來的名稱無法使用 ”“” @pytest.fixture(scope='function') def my_fixture(): print('這是前置內(nèi)容') yield print('這是后置內(nèi)容') class Testdemo(): def test01(self,my_fixture): print('這是test01') def test02(self): print('這是test02')
根據(jù)上面的結(jié)構(gòu),運行后輸出的內(nèi)容為
這是前置內(nèi)容
這是test01
這是后置內(nèi)容
這是前置內(nèi)容
這是test02
這是后置內(nèi)容
對于上述方法中傳入my_fixture的做法,主要是對比setup/teardown之類的更方便,不需要每個方法都在運行之前執(zhí)行一邊setup,而是在某個方法需要這種操作時在執(zhí)行
到此這篇關(guān)于pytest-fixture及其用法的文章就介紹到這了,更多相關(guān)pytest fixture用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Django makemigrations migrate執(zhí)行成功但不創(chuàng)建數(shù)據(jù)庫表的解決
這篇文章主要介紹了Django makemigrations migrate執(zhí)行成功但不創(chuàng)建數(shù)據(jù)庫表的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09基于Python實現(xiàn)船舶的MMSI的獲取(推薦)
工作中遇到一個需求,需要通過網(wǎng)站查詢船舶名稱得到MMSI碼,網(wǎng)站來自船訊網(wǎng)。這篇文章主要介紹了基于Python實現(xiàn)船舶的MMSI的獲取,需要的朋友可以參考下2019-10-10Python 機器學(xué)習(xí)庫 NumPy入門教程
在我們使用Python語言進行機器學(xué)習(xí)編程的時候,這是一個非常常用的基礎(chǔ)庫。本文針對Python 機器學(xué)習(xí)庫 NumPy入門教程,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-04-04