如何在pytest中使用parametrize为多参数函数正确传参?
问题描述
现有如下Python函数:
def underscore_concat(*args): return "_".join(filter(None, ([*args]))).upper()
如何使用pytest.mark.parametrize为该函数正确传递多个参数?以下是我尝试的写法(存在错误):
@pytest.mark.parametrize("a, result", [( ["underscore", "concat", "test"], "UNDERSCORE_CONCAT_TEST")]) def test_underscore_concat(a, result): assert underscore_concat(**a) == result
正确解法
你的代码存在两个核心问题:
- 调用函数时用了
**a,但a是列表,**用于传递字典形式的关键字参数,而函数定义用的是*args(接收可变长位置参数),应该用*a来解包列表作为位置参数传入。 - 测试用例的参数组织可以更直观,适配函数的参数特性。
下面提供两种可行的正确写法:
写法一:直接拆分固定数量参数
如果测试场景中传入的参数数量固定,可以把每个参数单独作为测试用例的元素,调用时直接传递:
import pytest def underscore_concat(*args): return "_".join(filter(None, ([*args]))).upper() @pytest.mark.parametrize("arg1, arg2, arg3, result", [ ("underscore", "concat", "test", "UNDERSCORE_CONCAT_TEST"), ("hello", "", "world", "HELLO_WORLD"), # 空字符串会被filter过滤 ("foo", None, "bar", "FOO_BAR") # None也会被filter过滤 ]) def test_underscore_concat(arg1, arg2, arg3, result): assert underscore_concat(arg1, arg2, arg3) == result
写法二:用列表传递可变长参数
如果需要测试参数数量不固定的场景,保持列表传参的形式,修正调用方式即可:
import pytest def underscore_concat(*args): return "_".join(filter(None, ([*args]))).upper() @pytest.mark.parametrize("args_list, result", [ (["underscore", "concat", "test"], "UNDERSCORE_CONCAT_TEST"), (["hello"], "HELLO"), (["a", "", "b", None, "c"], "A_B_C") ]) def test_underscore_concat(args_list, result): assert underscore_concat(*args_list) == result
关键说明
*args表示函数接受任意数量的位置参数,调用时用*加可迭代对象(列表、元组等),就能把元素逐个传递给函数。- 原函数中的
filter(None, [*args])会过滤掉None、空字符串这类“假值”,测试用例可以覆盖这类场景验证逻辑正确性。
内容的提问来源于stack exchange,提问作者Luice712
相关产品推荐
相关产品推荐

