天天看點

軟體測試 | pytest測試架構紙fixture進階

作者:霍格沃茲測試

簡介

fixture 即測試用例執行的環境準備和消理,fixture 主要的目的是為了提供一種可靠和可重複性的手段去 運作那些最基本的測試内容。比如測試網站的功能時,每個測試用例都要登入和登出,利用 fixture 就可 以隻做一次,否則每個測試用例都要做這兩步。

fixture 類似于 setup/teardown 機制,但 fixture 更靈活的完成測試的初始化以及資源清理工作。可以使 用它将你需要執行 setup 的測試用例傳入 fixture 函數名,不需要的測試用例可以不用傳遞,不傳遞 fixture 名的測試用例将不會執行 fixture 函數。它允許我們将複雜的測試需求歸納成更簡單、更有組織的 測試函數。 @pytest.fixture 與 @pytest.mark.parametrize 結合實作參數化

如果測試資料需要在 fixture 方法中使用,同時也需要在測試用例中使用,可以在使用 parametrize 的時 候添加一個參數 indirect=True ,pytest 可以實作将參數傳入到 fixture 方法中,也可以在目前的測試 用例中使用。

當 indirect 參數設定這個參數為 True 時,pytest 會把 argnames 當作函數去執行,将 argvalues 作 為參數傳入到 argnames 這個函數裡。建立“test_param.py”檔案,代碼如下:

# 方法名作為參數
test_user_data = ['Tome', 'Jerry']
@pytest.fixture(scope="module")
def login_r(request):
 # 通過request.param擷取參數
 user = request.param
 print(f"\n 登入使用者:{user}")
 return user
@pytest.mark.parametrize("login_r", test_user_data,indirect=True)
def test_login(login_r):
 a = login_r
 print(f"測試用例中login的傳回值; {a}")
 assert a != ""           

運作結果:

test_mark_paramize.py::test_login[Tome]
test_mark_paramize.py::test_login[Jerry]
============================== 2 passed in\
0.02s ===============================
Process finished with exit code 0
登入使用者:Tome PASSED [ 50%]測試用例中login的傳回值; Tome
登入使用者:Jerry PASSED [100%]測試用例中login的傳回值; Jerry           

上面的結果可以看出,當 indirect=True 時,會将 login_r 作為參數,test_user_data 被當作參數 傳入到 login_r 方法中,生成多條測試用例。通過 return 将結果傳回,當調用 login_r 可以擷取 到 login_r 這個方法的傳回資料。

fixture 間互相調用

fixture 可以作為參數傳遞給其它的 fixture 函數。

工作中可能不同的功能,依賴的資料,環境不一樣,需要定義多個功能函數。

比如:登入 fixture 函數中需要信賴連接配接資料庫的 fixture 函數。可以将這些功能函數都定義為 fixture, 然後通過傳遞 fixture 函數,實作功能之間的資料交換。

# contents of test_append.py
import pytest
@pytest.fixture
def connectDB():
 return "name,school"
@pytest.fixture
def login(connectDB):
 return [connectDB]
def test_string(login):
 pass           

測試用例/fixture 可以請求多個 fixture

下面是一個示例:

# contents of test_append.py
import pytest
# Arrange
@pytest.fixture
def first_entry():
 return "a"
# Arrange
@pytest.fixture
def second_entry():
 return 2
# Arrange
@pytest.fixture
def order(first_entry, second_entry):
 return [first_entry, second_entry]
# Arrange
@pytest.fixture
def expected_list():
 return ["a", 2, 3.0]
def test_string(order, expected_list):
 # Act
 order.append(3.0)
 # Assert
 assert order == expected_list           

Fixture 終結器(Teardown/Cleanup)

添加終結器

但如果 yield 之前的内容發生異常,将不會執行 yield 後面的内容。

對于這種情況,還可以直接向測試的 request 對象添加 “finalizer” 終結器函數實作這個功能(與 yield fixtures 類似的結果,但能力更強)。

舉個應用場景:

比如我們在讀取檔案的時候,需要打開檔案,擷取檔案流對象,定義一個關閉檔案的方法 close() , 在終結器中實作關閉操作。最後即使後面的代碼有異常,也會執行終結器裡面的操作。

@pytest.fixture(scope='module', autouse=True)
def operate_file(request):
 print("打開檔案")
 fs = open('./datas/data.yaml', mode="r")
 def close():
 print("關閉檔案")
 fs.close()
 request.addfinalizer(close)
 datas = yaml.safe_load(fs)
 raise ValueError
 print(datas)           

搜尋微信公衆号:TestingStudio霍格沃茲的幹貨都很硬核