pytest.mark.parametrize 传参

pytest.mark.parametrize 是pytest用来参数化测试的一个装饰器,它允许你为测试函数或测试类提供多组参数list, 这样就可以使用每组参数执行测试函数或测试类,实现参数化驱动,接收的是元组集

参数类型简介

pytest.mark.parametrize 可接收三个参数,常用的有两个,第一个是函数中需要引用的参数名,第二个是参数值,会自动解析参数值并赋值到参数名上,按顺序将最小的迭代单元赋值到参数上

参数名:必填参数,传字符串类型,字符串中可以定义一个或者多个参数名,用逗号分隔开

参数值:必填参数,可迭代的对象,比如列表、元组、集合等等, 注意:参数值可以使用变量,但是不能传装饰器

ids:可选参数,标记每一组数据,在测试输出中展示,如下图所示

基本用法

点击查看代码

复制代码
import pytest

# 单个参数
@pytest.mark.parametrize("number", [1, 2, 3])
def test_square(number):
    assert number * number == number**2

# 多个参数
@pytest.mark.parametrize("a, b, expected", [
    (1, 2, 3),
    (4, 5, 9),
    (10, -1, 9)
])
def test_add(a, b, expected):
    assert a + b == expected

高级用法

1. 参数化类(所有方法使用相同参数)

点击查看代码

复制代码
@pytest.mark.parametrize("n", [5, 10])
class TestMath:
    def test_double(self, n):
        assert n * 2 == 2 * n
        
    def test_triple(self, n):
        assert n * 3 == 3 * n

2. 嵌套参数化(参数组合)

点击查看代码

复制代码
@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_combinations(x, y):
    # 将生成4组测试: (0,2), (0,3), (1,2), (1,3)
    assert x + y == y + x

3. 使用ID自定义测试名称

点击查看代码

复制代码
@pytest.mark.parametrize("input, expected", [
    (3, 9),
    (4, 16),
    (5, 25)
], ids=["3^2=9", "4^2=16", "5^2=25"])  # 自定义测试ID
def test_square_ids(input, expected):
    assert input**2 == expected

4. 从函数动态生成参数

点击查看代码

复制代码
def generate_data():
    return [(i, i*10) for i in range(1, 4)]

@pytest.mark.parametrize("input, expected", generate_data())
def test_dynamic_params(input, expected):
    assert input * 10 == expected

5. 参数化+Fixture组合

点击查看代码

复制代码
@pytest.fixture
def db_connection():
    return {"status": "connected"}

@pytest.mark.parametrize("user", ["alice", "bob", "charlie"])
def test_users(db_connection, user):
    assert db_connection["status"] == "connected"
    print(f"Testing user: {user}")

最佳实践

1.参数命名:使用有意义的参数名

点击查看代码

复制代码
# 推荐
@pytest.mark.parametrize("username, password", [("user1", "pass1")])

# 不推荐
@pytest.mark.parametrize("a, b", [("user1", "pass1")])

2.复杂数据结构:使用字典提高可读性

点击查看代码

复制代码
@pytest.mark.parametrize("data", [
    {"input": {"a": 1, "b": 2}, "expected": 3},
    {"input": {"a": -1, "b": 1}, "expected": 0}
])
def test_complex(data):
    result = data["input"]["a"] + data["input"]["b"]
    assert result == data["expected"]

3.共享参数:定义在模块顶部

点击查看代码

复制代码
# 在文件顶部定义
COMMON_PARAMS = [
    (1, 1, 2),
    (2, 3, 5),
    (5, 5, 10)
]

@pytest.mark.parametrize("a, b, expected", COMMON_PARAMS)
def test_addition(a, b, expected):
    assert a + b == expected

4.跳过特定用例:使用 pytest.param

点击查看代码

复制代码
@pytest.mark.parametrize("a, b, expected", [
    (1, 2, 3),
    pytest.param(1, "a", TypeError, marks=pytest.mark.xfail),
    (5, 5, 10)
])
def test_mixed_types(a, b, expected):
    if isinstance(expected, type):
        with pytest.raises(expected):
            a + b
    else:
        assert a + b == expected