在前文章中,我們看到pytest_repeat源碼中有這樣一段
@pytest.fixture
def __pytest_repeat_step_number(request):marker = request.node.get_closest_marker("repeat")count = marker and marker.args[0] or request.config.option.count......
看到參數為request,我們知道fixture裝飾的函數入參,只能是其他fixture,所以這里request一定也是fixture。
那它到底怎么用呢?這篇文章將詳細介紹,并通過實戰項目加深理解。
request fixture
The request fixture is a special fixture providing information of the requesting test function.這是pytest官方文檔的介紹,意思就是請求fixture是一個特殊的fixture,提供請求測試函數的信息。
源碼直達(https://github.com/pytest-dev/pytest/blob/main/src/_pytest/fixtures.py),感興趣的朋友可以查看源碼FixtureRequest
文檔直達(https://docs.pytest.org/en/latest/reference/reference.html#pytest.FixtureRequest)
request.node
當前測試用例的節點對象,表示當前執行的測試用例。
可以使用該對象獲取測試用例的名稱、文件路徑、測試類等信息。
import pytest@pytest.fixture
def my_fixture(request):node = request.nodeprint(f"Current test case: {node.name}")print(f"Test file path: {node.fspath}")print(f"Test class: {node.getparent}")def test_demo(my_fixture):pass
輸出結果為:
Current test case: test_demo
Test file path: /Users/pxl/test_dir/test_demo.py
Test class: <bound method Node.getparent of <Function test_demo>>
fixture 使用了request 參數,并通過request.node 獲取了當前測試用例的相關信息。
具體來說,我們打印了當前測試用例的名稱、文件路徑和測試類名稱。
request.config
前運行的配置對象,表示當前 Pytest 的配置信息。可以使用該對象獲取命令行參數、配置文件設置等信息。
pytest.ini[pytest]
markers =p0: 冒煙p1: 功能
@pytest.fixture
def my_fixture(request):config = request.configprint(f"Command line arguments: {config.option}")print(f"INI file options: {config.getini('markers')}")
該 fixture 使用了 request 參數,并通過 request.config 獲取了當前 Pytest 的配置信息。
具體來說,我們打印了命令行參數和配置文件中的一個選項。
request.param
當前 fixture 的參數,表示當前 fixture 的實例所需的參數值
@pytest.fixture(params=[1, 2, 3])
def my_fixture(request):param_value = request.paramprint(f"Current parameter value: {param_value}")return param_value
該 fixture 使用了 request 參數,并通過 request.param 獲取了當前實例所需的參數值。
request.fixturename
返回當前 fixture 的名稱。
@pytest.fixture
def my_fixture(request):fixture_name = request.fixturenameprint(f"Current fixture name: {fixture_name}")
我們使用 request.fixturename 獲取了當前 fixture 的名稱,并將其打印出來.
request.fixturenames
返回當前測試函數所使用的所有 fixture 的名稱列表
@pytest.fixture
def my_fixture(request):passdef test_example(my_fixture, request):fixture_names = request.fixturenamesprint(f"Current fixture name: {fixture_names}")
我們使用 request.fixturenames獲取了test_example使用的所有 fixture 的名稱
request.cls
當前測試類的類對象。
class TestClass:@pytest.fixturedef my_fixture(self, request):class_obj = request.clsprint(f"Current class object: {class_obj}")
使用 request.cls 獲取了當前測試類的類對象,并將其打印出來。
request.addfinalizer(finalizer_func)
在 fixture 完成后執行指定的函數。
@pytest.fixture
def my_fixture(request):def finalizer_func():print("Finalizer function called")request.addfinalizer(finalizer_func)print("Fixture setup")
我們使用 request.addfinalizer() 方法注冊了一個 finalizer 函數 finalizer_func。
該函數將在 fixture 執行完畢后被調用,并打印一條消息。
request.applymarker(marker)
為當前測試用例或 fixture 應用指定的 marker。
@pytest.fixture
def my_fixture(request):request.applymarker(pytest.mark.slow)
我們使用 request.applymarker() 方法為當前 fixture 添加了一個 pytest.mark.slow 的標記。
這個標記可以被 Pytest 識別并用于特定的測試運行策略。
request.config.getoption(name)
獲取命令行選項的值。
@pytest.fixture
def my_fixture(request):my_option = request.config.getoption("--my_option")print(f"Value of --my_option: {my_option}")
我們使用 request.config.getoption() 方法獲取了命令行選項 --my_option 的值,并將其打印出來。
request.module
當前測試用例所屬的模塊對象
def my_fixture(request):module_obj = request.moduleprint(f"Current module object: {module_obj}")
我們使用 request.module 獲取了當前測試用例所屬的模塊對象,并將其打印出來
request.param_index
參數化 fixture 的參數索引
@pytest.fixture(params=[1, 2, 3])
def my_fixture(request):param_value = request.paramparam_index = request.param_indexprint(f"Current parameter value: {param_value}")print(f"Current parameter index: {param_index}")return param_value
我們對帶有參數的 my_fixture fixture 進行了參數化。
使用 request.param_index 可以獲取當前參數在參數列表中的索引,并將其打印出來。
request.keywords
當前測試用例的關鍵字集合
@pytest.fixture
def my_fixture(request):keywords = request.keywordsprint(f"Current test keywords: {keywords}")
我們使用 request.keywords 獲取了當前測試用例的關鍵字集合,并將其打印出來
request.getfixturevalue(fixturename)
獲取已注冊的 fixture 對象的值
import pytest@pytest.fixture
def my_fixture():return "Hello, Fixture!"def test_example(request):fixture_value = request.getfixturevalue("my_fixture")assert fixture_value == "Hello, Fixture!"
實戰
到這里request fixture的常用屬性和方法應該了解差不多了。更多屬性和方法,可以參考官方文檔。
接下來我們就利用request屬性實現數據庫環境的切換。看實現代碼
conftest.pydef pytest_addoption(parser):parser.addoption("--test", action="store_true", help="Run tests in test mode")@pytest.fixture(scope="session")
def config_parser(request):class Clazz(object):config = ConfigParser()config.read(config_path)section = 'test' if request.config.getoption("--test") else 'prod'log.info(f"section: {config.sections()}")db_host = config.get(section, 'host')db_port = config.get(section, 'port')db_username = config.get(section, 'username')db_password = config.get(section, 'password')db_database = config.get(section, 'database')api_url = config.get(section, 'url')return Clazz@pytest.fixture(scope="session")
def db_connection(config_parser):db_conn = MySQLDB(config_parser.db_host,int(config_parser.db_port),config_parser.db_username,config_parser.db_password,config_parser.db_database)yield db_conndb_conn.close()
config_parser 是一個會話級別的 fixture,它返回一個配置解析器對象。這個配置解析器對象可以讀取配置文件,并根據傳入的命令行參數 --test 來確定讀取哪個配置文件的特定部分(測試環境或生產環境)。
具體流程如下:
首先,在 pytest_addoption 函數中,通過調用 parser.addoption() 方法來添加一個命令行選項 --test,它的作用是告訴 pytest 在測試模式下運行。
在 config_parser fixture 中,我們首先創建了一個名為 Clazz 的類,它包含了從配置文件中讀取的各個配置項的值。
根據傳入的 --test 參數值,決定使用測試環境還是生產環境的配置。如果 --test 參數被指定,則使用配置文件中的 test 部分,否則使用 prod 部分。
通過 config.get() 方法獲取具體的配置項的值,例如 db_host、db_port、db_username 等。
最后,將 Clazz 類作為返回值,供其他測試代碼使用。
db_connection 是一個會話級別的 fixture,它返回一個數據庫連接對象。
這個對象在測試期間可以被使用,并在測試完成后進行關閉。
具體流程如下:
在 db_connection fixture 中,我們創建了一個 MySQLDB 對象,將從 config_parser fixture 中獲取的數據庫連接參數傳入。
使用 yield 語句將數據庫連接對象返回給測試代碼。yield 使得這個 fixture 可以在測試期間提供數據庫連接,而在測試完成后繼續執行下面的代碼。
在 yield 之后的代碼將在測試完成后執行,這里使用 db_conn.close() 來關閉數據庫連接。
可以看到我們正是使用request.config.getoption這個方法來 獲取命令行選項的值。
這段代碼展示了如何使用 pytest 的 fixture 來管理測試環境和資源的初始化和清理。
通過使用會話級別的 fixture,可以確保在整個測試會話期間只進行一次配置解析和數據庫連接操作,避免重復的開銷和不必要的操作。
后續
到這里我們有攻克了一個知識點request,不僅介紹了它的基本用法,也介紹了筆者在工作中真實使用場景。多加嘗試,才能印象深刻。
最后:?下方這份完整的軟件測試視頻教程已經整理上傳完成,需要的朋友們可以自行領取?【保證100%免費】
軟件測試面試文檔
我們學習必然是為了找到高薪的工作,下面這些面試題是來自阿里、騰訊、字節等一線互聯網大廠最新的面試資料,并且有字節大佬給出了權威的解答,刷完這一套面試資料相信大家都能找到滿意的工作。