關(guān)于自動(dòng)化測(cè)試框架pytest的Fixture固件
什么是固件
Fixture 翻譯成中文即是固件的意思。它其實(shí)就是一些函數(shù),會(huì)在執(zhí)行測(cè)試方法/測(cè)試函數(shù)之前(或之后)加載運(yùn)行它們,常見(jiàn)的如接口用例在請(qǐng)求接口前數(shù)據(jù)庫(kù)的初始連接,和請(qǐng)求之后關(guān)閉數(shù)據(jù)庫(kù)的操作。
我們之前在APP UI自動(dòng)化系列中已經(jīng)介紹過(guò) unittest 的相關(guān)測(cè)試固件,如setup
、teardown
等。而 pytest 中提供了功能更加豐富的Fixture
,用于實(shí)現(xiàn)setup
、teardown
功能。
定義方式
使用@pytest.fixture()
進(jìn)行定義,簡(jiǎn)單示例如下:
import pytest @pytest.fixture() def before(): print("連接數(shù)據(jù)庫(kù)")
調(diào)用方式
調(diào)用單個(gè)fixture函數(shù)
- 方式一,使用fixture函數(shù)名作為參數(shù)
import pytest @pytest.fixture() def before(): print("連接數(shù)據(jù)庫(kù)") # 調(diào)用before def test_01(before): print("執(zhí)行test_01")
- 方式二,使用
@pytest.mark.usefixtures('fixture函數(shù)名')
裝飾器
import pytest @pytest.fixture() def before(): print("連接數(shù)據(jù)庫(kù)") # 調(diào)用before @pytest.mark.usefixtures('before') def test_01(): print("執(zhí)行test_01")
- 方式三,使用
autouse
參數(shù)自動(dòng)執(zhí)行fixture
函數(shù)
import pytest # fixture函數(shù)定義的時(shí)候使用autouse參數(shù),作用域范圍內(nèi)的測(cè)試用例會(huì)自動(dòng)調(diào)用該fixture函數(shù) @pytest.fixture(autouse=True) def before(): print("連接數(shù)據(jù)庫(kù)") # 自動(dòng)調(diào)用before def test_01(): print("執(zhí)行test_01")
三種方式調(diào)用后的結(jié)果都如下:
我們可以看到,先執(zhí)行了fixture
函數(shù),再執(zhí)行測(cè)試函數(shù)。
調(diào)用多個(gè)fixture函數(shù)
import pytest @pytest.fixture() def before(): print("連接數(shù)據(jù)庫(kù)") @pytest.fixture() def before_s(): print("初始化數(shù)據(jù)") def test_01(before, before_s): print("執(zhí)行test_01")
調(diào)用多個(gè) fixture 函數(shù)時(shí),由前至后依次執(zhí)行,所以test_01()
調(diào)用時(shí)先執(zhí)行before
,再執(zhí)行before_s
。
對(duì)fixture函數(shù)重命名
定義fixture
函數(shù)時(shí),可以利用name
參數(shù)進(jìn)行重命名,方便用于調(diào)用,示例如下:
import pytest @pytest.fixture(name='db') def connect_order_db(): print("連接數(shù)據(jù)庫(kù)") def test_01(db): print("執(zhí)行test_01")
使用fixture傳遞測(cè)試數(shù)據(jù)
在執(zhí)行完fixture
函數(shù)后,有時(shí)需要將該fixture
中得到到某些數(shù)據(jù)傳遞給測(cè)試函數(shù)/測(cè)試方法,用于后續(xù)的執(zhí)行。
fixture
中提供普通傳遞和參數(shù)化傳遞兩種數(shù)據(jù)傳遞方式。
普通傳遞
示例如下:
import pytest @pytest.fixture() def before(): print("連接數(shù)據(jù)庫(kù)") return "連接成功!" def test_01(before): print("執(zhí)行test_01") assert before == "連接成功!"
注意,如果自定義的fixture
函數(shù)有返回值,需要使用上面說(shuō)的方式一調(diào)用才能獲取fixture
函數(shù)的返回值并傳入測(cè)試函數(shù)中,方式二就無(wú)法獲取返回值。
參數(shù)化傳遞
對(duì)fixture
函數(shù)進(jìn)行參數(shù)化時(shí),需要使用參數(shù)params
,并且需要傳入?yún)?shù)request
,簡(jiǎn)單示例如下:
import pytest test_params = [1, 2, 0] @pytest.fixture(params=test_params) def before(request): result = request.param return result def test_02(before): print("執(zhí)行test_02") assert before if __name__ == '__main__': pytest.main()
執(zhí)行結(jié)果:
可以看到,因?yàn)樗{(diào)用的fixture函數(shù)進(jìn)行了參數(shù)化,雖然只有一個(gè)測(cè)試函數(shù)但執(zhí)行了3次。
conftest.py
上面我們舉的例子都是把fixture函數(shù)放在測(cè)試用例模塊里面,但如果很多測(cè)試模塊需要引用同一個(gè)fixture函數(shù)怎么辦,這是時(shí)候就需要把它放在命名為conftest
的模塊里,這樣同級(jí)或以下目錄中的測(cè)試用例便能調(diào)用這些自定義的fixture函數(shù)。
例如,有如下目錄:
├─testcase │ │ │ ├─test_module_01 │ │ test_case_1.py │ │ test_case_2.py │ │ │ ├─test_module_02 │ │ test_case_3.py
test_module_01 中的test_case_1.py
與test_case_2.py
都需要調(diào)用同一個(gè) fixture 函數(shù),那么我們只需要在 test_module_01 中新建conftest.py
并編寫(xiě)這個(gè)fixture
函數(shù)即可,示例如下:
├─testcase │ │ │ ├─test_module_01 │ │ conftest.py │ │ test_case_1.py │ │ test_case_2.py │ │ │ ├─test_module_02 │ │ test_case_3.py
conftest.py
:
import pytest @pytest.fixture(autouse=True) def before(): print("連接數(shù)據(jù)庫(kù)")
test_case_1.py
:
def test_01(): print("執(zhí)行test_01")
test_case_2.py
:
def test_02(): print("執(zhí)行test_02")
這樣,執(zhí)行這兩個(gè)模塊的測(cè)試用例時(shí)會(huì)自動(dòng)先去調(diào)用conftest.py
中的before()
函數(shù)。
假設(shè) test_module_02 中的 test_case_3.py 也需要調(diào)用這個(gè)before()
函數(shù),那么這個(gè)時(shí)候我們就需要在上一層即 testcase 中新建conftest.py
并編寫(xiě)這個(gè)before()
函數(shù),才能在 test_case_3.py 中調(diào)用,如下:
├─testcase │ │ conftest.py │ │ │ ├─test_module_01 │ │ conftest.py │ │ test_case_1.py │ │ test_case_2.py │ │ │ ├─test_module_02 │ │ test_case_3.py
conftest.py
只作用于同級(jí)
或以下
目錄中的測(cè)試模塊,且需要注意,當(dāng)以下
層級(jí)中存在了另一個(gè)conftest.py
,那么以下層級(jí)將由另一個(gè)conftest.py
文件接管。
作用域
pytest 的 fixture 作用域分session
、module
、class
、function
四個(gè)級(jí)別。在定義 fixture 函數(shù)的時(shí)候通過(guò)scope
參數(shù)指定作用范圍,默認(rèn)為function
。
session
,每次會(huì)話(huà)執(zhí)行一次module
,每個(gè)測(cè)試模塊執(zhí)行一次class
,每個(gè)測(cè)試類(lèi)執(zhí)行一次function
,每個(gè)測(cè)試方法執(zhí)行一次
注意,對(duì)于單獨(dú)定義的測(cè)試函數(shù),class、function 都會(huì)起作用,可以從下列示例中看出來(lái)。
測(cè)試目錄結(jié)構(gòu)如下:
├─apiAutoTest │ │ run.py │ │ │ ├─testcase │ │ │ conftest.py │ │ │ │ │ ├─test_module_02 │ │ │ │ conftest.py │ │ │ │ test_case_3.py │ │ │ │ test_case_4.py
其中conftest.py
代碼如下:
import pytest @pytest.fixture(scope="session", autouse=True) def session_fixture(): print("這是一個(gè)作用于session的fixture") @pytest.fixture(scope="module", autouse=True) def module_fixture(): print("這是一個(gè)作用于module的fixture") @pytest.fixture(scope="class", autouse=True) def class_fixture(): print("這是一個(gè)作用于class的fixture") @pytest.fixture(scope="function", autouse=True) def function_fixture(): print("這是一個(gè)作用于function的fixture")
test_case_3.py
代碼如下:
import pytest class TestOrder: def test_a(self): print("test_a") def test_b(self): print("test_b") def test_c(): print("test_c")
test_case_4.py
代碼如下:
def test_e(): print("test_e")
run.py
代碼如下:
import pytest if __name__ == '__main__': pytest.main(["-s"])
運(yùn)行run.py
,結(jié)果如下:
collected 4 items testcase\test_module_02\test_case_3.py 這是一個(gè)作用于session的fixture 這是一個(gè)作用于module的fixture 這是一個(gè)作用于class的fixture 這是一個(gè)作用于function的fixture test_a .這是一個(gè)作用于function的fixture test_b .這是一個(gè)作用于class的fixture 這是一個(gè)作用于function的fixture test_c . testcase\test_module_02\test_case_4.py 這是一個(gè)作用于module的fixture 這是一個(gè)作用于class的fixture 這是一個(gè)作用于function的fixture test_e . ============================== 4 passed in 0.04s ==============================
從結(jié)果可以看出來(lái):
- 作用于
session
的fixture函數(shù)只在所有測(cè)試用例執(zhí)行之前調(diào)用了一次 - 作用于
module
的fixture函數(shù)在每個(gè)測(cè)試模塊執(zhí)行之前調(diào)用了一次 - 作用于
class
的fixture函數(shù)在每個(gè)測(cè)試類(lèi)執(zhí)行之前調(diào)用了一次 - 作用于
function
的fixture函數(shù)在每個(gè)測(cè)試方法/測(cè)試函數(shù)執(zhí)行之前調(diào)用了一次
注意,在定義的測(cè)試函數(shù)(如test_c()
、test_e()
)執(zhí)行之前也會(huì)調(diào)用scope=class的fixture函數(shù)。
總結(jié)
與 unittest 框架比較,pytest 中的Fixture
更加豐富,可擴(kuò)展性更高。
Fixture
還有很多更加優(yōu)雅的用法用于自動(dòng)化測(cè)試項(xiàng)目中,本文只是以最簡(jiǎn)單的示例進(jìn)行說(shuō)明。
到此這篇關(guān)于關(guān)于自動(dòng)化測(cè)試框架pytest的Fixture固件的文章就介紹到這了,更多相關(guān)自動(dòng)化測(cè)試Fixture固件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
把大數(shù)據(jù)數(shù)字口語(yǔ)化(python與js)兩種實(shí)現(xiàn)
當(dāng)出現(xiàn)萬(wàn)以上的整型數(shù)字時(shí),經(jīng)常要把它們口語(yǔ)化比較直觀。下面分享兩段代碼,python與js的2013-02-02Python 中如何使用 setLevel() 設(shè)置日志級(jí)別
這篇文章主要介紹了在 Python 中使用setLevel() 設(shè)置日志級(jí)別,Python 提供了一個(gè)單獨(dú)的日志記錄模塊作為其標(biāo)準(zhǔn)庫(kù)的一部分,以簡(jiǎn)化日志記錄,本文將討論日志記錄 setLevel 及其在 Python 中的工作方式,需要的朋友可以參考下2023-07-07python中的selenium實(shí)現(xiàn)自動(dòng)向下滾動(dòng)頁(yè)面并指定最大滑動(dòng)距離
這篇文章主要介紹了python中的selenium實(shí)現(xiàn)自動(dòng)向下滾動(dòng)頁(yè)面并指定最大滑動(dòng)距離,下文有關(guān)selenium的資料介紹有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-02-02Python實(shí)現(xiàn)單詞拼寫(xiě)檢查
這篇文章主要介紹了Python實(shí)現(xiàn)單詞拼寫(xiě)檢查,本文講解了單詞拼寫(xiě)檢查的一些知識(shí)并給出兩種實(shí)現(xiàn)方法,需要的朋友可以參考下2015-04-04python基于爬蟲(chóng)+django,打造個(gè)性化API接口
這篇文章主要介紹了python基于爬蟲(chóng)+django,打造個(gè)性化API接口的方法,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01Python并發(fā)爬蟲(chóng)常用實(shí)現(xiàn)方法解析
這篇文章主要介紹了Python并發(fā)爬蟲(chóng)常用實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11python cx_Oracle模塊的安裝和使用詳細(xì)介紹
這篇文章主要介紹了python cx_Oracle模塊的安裝和使用詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-02-02吳恩達(dá)機(jī)器學(xué)習(xí)練習(xí):SVM支持向量機(jī)
這篇文章主要為我們帶來(lái)了吳恩達(dá)機(jī)器學(xué)習(xí)的一個(gè)練習(xí):SVM支持向量機(jī),通過(guò)本次練習(xí)相信你能對(duì)機(jī)器學(xué)習(xí)深入更進(jìn)一步,需要的朋友可以參考下2021-04-04Python執(zhí)行外部命令subprocess的使用詳解
subeprocess模塊是python自帶的模塊,無(wú)需安裝,主要用來(lái)取代一些就的模塊或方法,本文通過(guò)實(shí)例代碼給大家分享Python執(zhí)行外部命令subprocess及使用方法,感興趣的朋友跟隨小編一起看看吧2021-05-05