在之前的分享中,我們知道可以使用yield
或者return
關鍵字把fixture函數
裡的值傳遞給test函數
。
這種方法很實用,比如我在fixture函數
裡向資料庫裡插入必要的測試資料,那我就可以把相關資料返回給test函數
用來做相關斷言查詢等操作。
那如果我想把test函數
(也就是測試用例)中的資料傳給fixture函數
使用,要如何實現呢?
直接先貼上一段範例程式碼:
import pytest
@pytest.fixture
def fixt(request):
marker = request.node.get_closest_marker("fixt_data")
if marker is None:
# Handle missing marker in some way...
data = None
else:
data = marker.args[0]
# Do something with the data
return data
@pytest.mark.fixt_data(42)
def test_fixt(fixt):
assert fixt == 42
程式碼中可能有2個知識點,可能有的小夥伴並不熟悉,分別來看下。
什麼是mark
標記,幹什麼用?
標記
可以將後設資料應用於測試函數(注意,不能是fixture函數),後續可以通過fixture函數
或者plugins外掛
進行存取。
框架有一些內建
的marks,也可以支援我們自定義
。
內建的在之前的系列分享中有出現過幾個,比如:
pytest.mark.parametrize
:引數化pytest.mark.skip
:跳過測試用例pytest.mark.skipif
: 根據條件跳過用例其他就不展開了,上述提到的分享文章連結會附在文末。
而在上述範例程式碼中,pytest.mark.fixt_data
則是屬於自定義的mark標記,fixt_data
我也可以改成fixt_pingguo
也是可以的。
request
本身也是一個fixture函數,但是很特殊
,用於提供當前正在執行請求的上下文資訊。
在上述範例程式碼中,測試函數test_fixt
請求了fixture函數fixt
,那麼在這次請求中相關聯到的資訊就可以在request
中獲得。
比如:
fixturename
: 當前這個fixture函數的名稱module
: 當前測試函數所在的模組scope
:當前fixture函數作用範圍node
:基於當前測試範圍蒐集到的底層節點物件,這裡又包含了很多資訊。就不一一展開了,有興趣的童鞋可以在編輯器裡打個斷點,檢視對應的資訊詳情。
回到範例程式碼,我們可以先直接執行一下程式碼。
測試是通過的(warning先忽略,因為沒有註冊自定義的mark),也就是說@pytest.mark.fixt_data(42)
中的42
是成功的帶到了fixture函數
中,經過函數中的處理後最後返回出來。
其中的get_closest_marker("fixt_data")
方法,是返回與名稱fixt_data
匹配的第一個mark,從最近的級別到更遠的級別,比如從函數到模組級別。
所以在這裡,被找到的mark就是我們自定義的這個@pytest.mark.fixt_data(42)
標記了。
標記是使用工廠物件pytest.mark
動態建立的,用於裝飾器,所以我們可以用語法糖@
直接使用即可。
mark物件被建立之後,就被會收集起來,然後可以通過fixture
或帶有Node.iter_markers
的勾點函數存取,可以存取到這個mark物件的屬性。
有 2 個屬性:
mark.args
:這是個元組mark.kwargs
:這是個字典所以我們可以使用上面的方式來進行傳參,比如現在新建一個自定義mark:
@pytest.mark.timeout(10, "slow", method="thread")
def test_function():
...
這裡傳參實際上就是
mark.args == (10, "slow")
mark.kwargs == {"method": "thread"}
回到最上方的範例程式碼,在fixture函數
中就可以使用data = marker.args[0]
來獲取到引數42
。
如果在測試函數上同時使用了多個自定義mark
,那麼舉例測試函數最近的mark就會被首先迭代。比如:
@pytest.mark.timeout(10, "slow", method="thread")
@pytest.mark.slow
def test_function():
...
結果就是先@pytest.mark.slow
,然後是@pytest.mark.timeout
。
在執行最上方的範例程式碼時出現了一個warning,因為我們沒有註冊自定義的標記導致,現在來進行註冊。
新建pytest.ini
組態檔,在裡面新增即可:
[pytest]
markers =
fixt_data: pingguo test
fixt_data2
這裡冒號:
後面的描述是可選的,比如fixt_data2
就是沒有新增描述。
重新執行下最上方的程式碼:
platform win32 -- Python 3.9.12, pytest-7.1.3, pluggy-1.0.0
rootdir: D:\PythonCode\my_python, configfile: pytest.ini
collected 1 item
usemarks.py .
============================== 1 passed in 0.00s ==============================
Process finished with exit code 0
註冊完成。
pytest合集見連線