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

如何用pytest实现动态测试名并分别统计各测试用例结果

如何用pytest将字典条目拆分为独立测试用例?

你希望通过两个字典(expected存储预期输出,actual存储实际输出)创建多测试用例,让pytest分别报告每个字典条目的测试结果,但当前基于fixture的写法仅显示“1个测试通过”,无法实现“2个测试通过”的统计效果。

你的基础代码

import pytest
from dataclasses import dataclass
from typing import Dict


@dataclass
class OutputsToCheck:
    a: int
    b: int


expected: Dict[str, OutputsToCheck] = {
    "test_1": OutputsToCheck(a=1, b=2),
    "test_2": OutputsToCheck(a=3, b=4),
}

actual: Dict[str, OutputsToCheck] = {
    "test_1": OutputsToCheck(a=1, b=2),
    "test_2": OutputsToCheck(a=3, b=4),
}

你尝试的代码

@pytest.fixture
def test_names():
    return ["test_1", "test_2"]


@pytest.fixture
def expected_outputs():
    return expected


@pytest.fixture
def actual_outputs():
    return actual


@pytest.fixture
def make_test(expected_outputs, actual_outputs):
    def test(test_name: str):
        expected = expected_outputs[test_name]
        actual = actual_outputs[test_name]
        assert expected == actual

    return test


@pytest.fixture
def make_tests(make_test, test_names):
    output = {}
    for name in test_names:
        output[name] = make_test(name)
    return output


def test(make_tests, test_names):
    for name in test_names:
        make_tests[name]

问题原因

你当前的写法是在单个测试函数里循环执行断言逻辑,pytest会将整个函数视为一个测试用例,因此无论内部执行多少次断言,最终只会统计为1个测试结果。

解决方案:使用pytest参数化测试

要让每个字典条目对应独立的测试用例,需要用到pytest的参数化功能,以下两种方式都能实现需求:

方式1:直接用@pytest.mark.parametrize

通过参数化测试名称,让pytest为每个字典条目生成独立测试:

import pytest
from dataclasses import dataclass
from typing import Dict


@dataclass
class OutputsToCheck:
    a: int
    b: int


expected: Dict[str, OutputsToCheck] = {
    "test_1": OutputsToCheck(a=1, b=2),
    "test_2": OutputsToCheck(a=3, b=4),
}

actual: Dict[str, OutputsToCheck] = {
    "test_1": OutputsToCheck(a=1, b=2),
    "test_2": OutputsToCheck(a=3, b=4),
}


@pytest.mark.parametrize("test_name", expected.keys())
def test_outputs(test_name):
    assert expected[test_name] == actual[test_name]

运行后pytest会显示2个测试用例,每个对应字典中的一个条目,失败时会明确标注是哪个test_name出现问题。

方式2:用pytest_generate_tests动态生成测试

如果需要从外部动态加载测试用例(比如从文件读取字典),可以使用pytest的钩子函数:

import pytest
from dataclasses import dataclass
from typing import Dict


@dataclass
class OutputsToCheck:
    a: int
    b: int


expected: Dict[str, OutputsToCheck] = {
    "test_1": OutputsToCheck(a=1, b=2),
    "test_2": OutputsToCheck(a=3, b=4),
}

actual: Dict[str, OutputsToCheck] = {
    "test_1": OutputsToCheck(a=1, b=2),
    "test_2": OutputsToCheck(a=3, b=4),
}


def pytest_generate_tests(metafunc):
    # 为带有test_name参数的测试函数生成参数
    if "test_name" in metafunc.fixturenames:
        metafunc.parametrize("test_name", expected.keys())


def test_outputs(test_name):
    assert expected[test_name] == actual[test_name]

这个方法会在测试收集阶段自动为test_outputs函数生成参数,效果和方式1一致,适合测试用例数量不固定的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:24:50