pytest使用parametrize将参数化变量传递到fixture
本文介绍如何在pytest中将测试用例参数传递给fixture函数。通过结合@pytest.mark.parametrize的indirect=True和request.param,实现顶层与子级conftest.py间token等数据的共享,确保测试前置条件获取正确凭证。
本文介绍在pytest测试框架中,如何将测试脚本内的变量成功传递给fixture函数的具体方法。
一、应用场景背景
- 当前项目结构中,根目录包含一个conftest.py文件,其中定义了一个生成API Token的fixture函数,命名为gen_token()。
- 每个测试模块目录下也设有各自的conftest.py,用于存放该模块专用的fixture函数,例如名为setup_before()的函数。
- 由于获取Token是发起接口请求的前提条件,因此在具体的测试用例test_case()中,需要直接调用顶层的fixture函数,即通过参数形式传入gen_token。
- 顶层的gen_token()函数需要接收3个参数。由于不同测试用例可能涉及生成不同用户的Token,因此将这些参数定义在具体的case文件中。
以上是整体的项目背景说明。
现有一项新需求:在setup_before()函数中执行数据构造操作,该操作需要请求另一个接口,而此请求同样依赖于Token。
由此,核心问题转化为:
- 如何将case文件中的参数传递到fixture函数中。
- 确保gen_token()返回的值,能够同时被setup_before()和test_case()获取并使用。
二、解决方案:使用@pytest.mark.parametrize与fixture调用
以下将实际代码抽象为简化示例,以便演示和理解核心逻辑:
# 目录结构
-- /demo_top
-- /demo_sub
__init__.py
conftest.py
test_case.py
__init__.py
conftest.py以下分别展示了/demo_top/conftest.py、/demo_top/demo_sub/conftest.py以及/demo_top/demo_sub/test_case.py的具体内容。
1. /demo_top/conftest.py
# content of /demo_top/conftest.py
import pytest
@pytest.fixture()
def gen_token(request):
params = request.param
print("\n根目录下gen_token()拿到的参数:", params)
if params[0] + params[1] == 5:
return "api_token"
else:
return None此处模拟生成Token的fixture函数。当传入的参数相加等于5时,返回字符串"api_token";否则返回None。
2. /demo_top/demo_sub/conftest.py
# content of /demo_top/demo_sub/conftest.py
import pytest
@pytest.fixture()
def setup_before(request, gen_token):
print("执行子级setup_before,拿到的传参:", request.param)
print("执行子级setup_before,拿到gen_token的返回值:", gen_token)
if gen_token:
yield "造数完成"
print("测试用例test_case执行完毕,清理测试数据")
else:
pytest.skip("跳过")此处模拟为测试用例准备数据的fixture函数。如果未能获取到Token,则直接跳过该测试用例。
3. /demo_top/demo_sub/test_case.py
# content of /demo_top/demo_sub/test_case.py
import pytest
test_param = [(1, 4)]
@pytest.mark.parametrize("gen_token", test_param, indirect=True)
@pytest.mark.parametrize("setup_before", test_param, indirect=True)
def test_case1(gen_token, setup_before):
print("\n测试用例里拿到的gen_token返回值:", gen_token)
print("测试用例里拿到的setup_before返回值:", setup_before)
print("执行测试用例test_case1...")
if __name__ == '__main__':
pytest.main(['-s', 'test_case.py'])这是具体的测试用例文件。其中包含一个测试函数test_case1,由于它需要用到两个fixture函数返回的值,因此同时请求了gen_token和setup_before。
参数传递机制
- @pytest.mark.parametrize:利用pytest内置的parametrize装饰器,将参数传递给目标fixture函数。只需在希望接收参数的fixture函数名上添加该装饰器即可,例如这里的gen_token和setup_before,注意名称必须与fixture定义名称一致。
- indirect=True:该参数的作用是让parametrize中的参数名称(如"gen_token")被视为函数执行,并将后续的参数值(如test_param)作为该函数的传参。
- request.param:接收传参的fixture函数,通过request.param属性来获取具体的参数值。
fixture之间的相互调用
关于fixture之间的相互调用,此前文章已有详述。既然setup_before依赖于gen_token,直接进行传递调用即可,即setup_before(request, gen_token)。
在各环节添加了print语句以打印信息,帮助理解执行过程。
test_case.py [100%]
============================== 1 passed in 0.08s ==============================
根目录下gen_token()拿到的参数: (1, 4)
执行子级setup_before,拿到的传参: (1, 4)
执行子级setup_before,拿到gen_token的返回值: api_token
.
测试用例里拿到的gen_token返回值: api_token
执行测试用例test_case1...
测试用例test_case执行完毕,清理测试数据
Process finished with exit code 0再观察gen_token不返回有效Token的情况,将传参修改为test_param = [(2, 4)]。
test_case.py [100%]
============================= 1 skipped in 0.08s ==============================s
根目录下gen_token()拿到的参数: (2, 4)
执行子级setup_before,拿到的传参: (2, 4)
执行子级setup_before,拿到gen_token的返回值: None
Skipped: 跳过
Process finished with exit code 0此时测试用例将被跳过,不执行。
以上即为pytest使用parametrize将参数化变量传递到fixture的详细内容,更多关于pytest parametrize变量传递fixture的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













