You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过pytest parametrize向fixture传递函数而非可迭代对象?

pytest parametrize 向fixture传递函数的正确方式

核心结论

可以通过parametrize向fixture传递函数,但不能直接传函数对象(否则pytest会把它当成可迭代对象遍历,触发非预期错误),需要把函数包装成可迭代的参数列表,或者在fixture里正确接收并调用函数。

你的示例代码问题分析

你的代码存在两个关键错误:

  1. @pytest.mark.parametrize("fixt", sample_data, indirect=True) 中,sample_data是函数对象,pytest会尝试遍历它,导致不符合预期的行为;
  2. fixturefixt里直接把request赋值给sample_data,正确做法是用request.param获取parametrize传递的参数。

修正后的示例代码

方式1:传递函数的返回值

如果只需要函数生成的数据,直接调用函数并包装成列表即可:

import pytest

@pytest.fixture
def sample_data():
    data = 1
    return data

@pytest.fixture
def fixt(request):
    # 通过request.param获取传递的参数
    data = request.param
    return data

# 传递sample_data()的结果,包装成列表(parametrize要求第二个参数是可迭代对象)
@pytest.mark.parametrize("fixt", [sample_data()], indirect=True)
def test_indirect(fixt):
    assert fixt == 1

方式2:直接传递函数,在fixture里调用

如果需要动态调用不同函数生成数据,可以把函数本身作为参数传递,在fixture内执行:

import pytest

@pytest.fixture
def sample_data():
    return 1

@pytest.fixture
def another_data():
    return 2

@pytest.fixture
def fixt(request):
    # request.param是传递过来的函数,调用它获取数据
    data_func = request.param
    return data_func()

# 传递函数对象,包装成列表
@pytest.mark.parametrize("fixt", [sample_data, another_data], indirect=True)
def test_indirect(fixt):
    assert fixt in (1, 2)

解决你实际项目中的错误

你遇到的TypeError: object of type 'SubRequest' has no len(),是因为fixture里错误使用request而非request.param,导致测试用例拿到的是SubRequest对象而非目标Dataframe。修正步骤如下:

  1. 在接收参数的fixture里,用df = request.param获取传递的Mock Dataframe(或生成它的函数);
  2. parametrize时,把你的MagicMock Dataframe(或生成它的函数)包装成列表。示例代码:
from unittest.mock import MagicMock
import pytest

@pytest.fixture
def mock_df_fixture(request):
    # 获取传递的mock dataframe
    mock_df = request.param
    return mock_df

# 定义不同的mock dataframe
def get_mock_df_1():
    df = MagicMock()
    df.__len__.return_value = 5
    return df

def get_mock_df_2():
    df = MagicMock()
    df.__len__.return_value = 10
    return df

# 传递生成mock df的函数结果,或直接传递mock df对象
@pytest.mark.parametrize("mock_df_fixture", [get_mock_df_1(), get_mock_df_2()], indirect=True)
def test_df_length(mock_df_fixture):
    assert len(mock_df_fixture) in (5, 10)

内容的提问来源于stack exchange,提问作者BobJones_heavyhitter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 18:42:54