Playwright/Pytest API测试:如何在参数化用例中传递APIRequestContext并实现独立测试结果展示
Playwright/Pytest API测试:如何在参数化用例中传递APIRequestContext并实现独立测试结果展示
我帮你梳理下问题所在,然后给出具体的修正方案。核心问题是你错误地在装饰器中尝试硬传api_request_context fixture——fixture是pytest在测试运行阶段才会实例化的对象,而装饰器是在代码导入阶段执行的,这时候fixture还不存在,自然拿不到正确的实例。另外你的自定义装饰器写法可以简化,让pytest自动处理fixture注入和参数传递。
第一步:修正commonlib.py中的问题
先把工具函数里的语法错误和装饰器逻辑修正:
- 修复
extract_data_from_excel的参数引号错误 - 简化
dict_parametrizes装饰器,不再手动处理测试参数,让pytest自动透传所有参数(包括fixture) - 修正变量名拼写错误
修正后的commonlib.py代码:
import pytest def dict_parametrizes(test_data): """Custom decorator to parametrize a test function from a dictionary with custom IDs.""" def decorator(test_func): # 构造测试用例列表:(TC_NAME, BODY, EXPECTED) test_cases = [(tc_name, data["Body"], data["EXPECTED"]) for tc_name, data in test_data.items()] # 直接用TC_NAME作为测试用例ID,更简洁 test_ids = list(test_data.keys()) @pytest.mark.parametrize( "TC_NAME, BODY, EXPECTED", test_cases, ids=test_ids ) # 简化wrapper:直接透传所有参数,pytest会自动注入fixture def wrapper(*args, **kwargs): return test_func(*args, **kwargs) return wrapper return decorator def extract_data_from_excel(file, worksheet, tc_name_col, body_col, expected_col): """从Excel提取数据,返回格式:{TC_NAME: {"Body": ..., "EXPECTED": ...}}""" # 这里替换成你的实际Excel解析逻辑(比如用openpyxl/pandas) # 示例实现供参考 testdata_dictionary = { "TC001": {"Body": {"user_id": 1}, "EXPECTED": {"status": 200, "data": {"name": "Alice"}}}, "TC002": {"Body": {"user_id": 2}, "EXPECTED": {"status": 200, "data": {"name": "Bob"}}}, "TC003": {"Body": {"user_id": 999}, "EXPECTED": {"status": 404, "message": "User not found"}} } return testdata_dictionary def get_auth_token(api_request_context, env): # 你的token获取逻辑实现 return "dummy_access_token" def get_user_information(api_request_context, access_token): # 你的用户信息获取逻辑实现 return {"user_id": 1, "name": "Alice"}
第二步:修正test.py中的测试用例
测试用例中不需要手动声明setup_env(因为你设了autouse=True,pytest会自动执行),只需要在测试函数中声明api_request_context fixture,pytest会自动注入它。
修正后的test.py代码:
import pytest from playwright.sync_api import Playwright, APIRequestContext from commonlib import dict_parametrizes, extract_data_from_excel, get_auth_token # 1. 提前从Excel加载测试数据 test_data = extract_data_from_excel( file="testdata.xlsx", worksheet="Solutions", tc_name_col="TC_NAME", body_col="BODY", expected_col="EXPECTED" ) # 2. 定义API请求上下文fixture @pytest.fixture(scope="function") def api_request_context(playwright: Playwright, env: str) -> APIRequestContext: # 替换成你的API上下文初始化逻辑,比如设置base_url api_context = playwright.request.new_context(base_url="https://your-api-domain.com") yield api_context api_context.dispose() # 3. 全局环境初始化,autouse=True会自动在会话开始时执行 @pytest.fixture(scope="session", autouse=True) def setup_env(): global access_token # 如果需要依赖api_request_context,可将scope改为function并声明依赖 access_token = "dummy_global_access_token" # 4. 测试用例:使用自定义装饰器实现参数化 @pytest.mark.tags("all", "regression") @dict_parametrizes(test_data) def test_user_api(TC_NAME, BODY, EXPECTED, api_request_context: APIRequestContext): """测试用户API,每个TC_NAME对应独立测试实例""" # 你的API调用逻辑 response = api_request_context.post( "/api/user/info", json=BODY, headers={"Authorization": f"Bearer {access_token}"} ) # 结果断言 assert response.status == EXPECTED["status"] response_json = response.json() if EXPECTED["status"] == 200: assert response_json["data"]["name"] == EXPECTED["data"]["name"] else: assert response_json["message"] == EXPECTED["message"]
关键问题解释
你之前的写法出错的核心原因:
- 装饰器在代码导入阶段就执行了,而
api_request_contextfixture是pytest在测试运行阶段才创建的实例,导入阶段根本拿不到有效实例 - 修正后的写法让pytest自动处理参数传递和fixture注入,不需要手动干预
最终效果
运行测试后,每个用例会以TC_NAME作为ID独立展示结果,比如:
test.py::test_user_api[TC001] PASSED test.py::test_user_api[TC002] PASSED test.py::test_user_api[TC003] PASSED
备注:内容来源于stack exchange,提问作者AutoTest
相关产品推荐
相关产品推荐

