Late-Binding 与 Pytest 模块冲突

Late-Binding conflict with Pytest module

我正在尝试迭代 pytest 函数,late-binding 的问题 使 pytest 仅将测试应用于最后一个函数。
为了简化示例,我编写了以下 test.py 文件:

import pytest


def func_1(x):
    return (x+10)


def func_2(y):
    return (y-10)


func_1_test_cases = {'func_1': (10, 20)}
func_2_test_cases = {'func_2': (10, 0)}

# Iterating over the functions 
for func in ['func_1', 'func_2']:
    @pytest.mark.parametrize('param, expected',
                             globals()[func + '_test_cases'].values(),
                             ids=list(globals()[func +
                                                '_test_cases'].keys()))
    def test(param, expected):
        eval(func+'(param) == expected')

我阅读了有关 late-binding 问题的更多信息并采纳了以下建议:

    def test(param, expected, func=func):
        eval(func+'(param) == expected')

使用命令时: pytest test.py -v
pytest 报告仅收集列表中的最后一个函数 (func_2):

plugins: timeout-1.4.2, anyio-2.2.0, pudb-0.7.0 collected 1 item

1.py::test[func_2] PASSED [100%]

============================================================================= 1 passed in 0.01s =============================================================================

func_1从未收藏过
使用 pytest 时,late-binding 问题似乎更棘手。 我希望 pytest 报告收集两个函数和 return 它们的状态。 我真的需要解决这个问题。

这并没有直接回答您关于使用相同名称定义多个测试的问题,但是对于您发布的特定示例,将函数本身作为测试参数之一包括在内会容易得多:

import pytest

def func_1(x):
    return (x+10)

def func_2(y):
    return (y-10)

@pytest.mark.parametrize(
        'func,param,expected', [
            pytest.param(func_1, 10, 20, id='func_1'),
            pytest.param(func_2, 10, 0, id='func_2'),
        ],
)
def test(func, param, expected):
    assert func(param) == expected

请注意:您的测试函数没有 assert,因此无论 eval(func+'(param) == expected') 是真还是假,它都会通过。

受Kale回答的启发,我认为没有很好的方法可以循环遍历pytest parametize装饰器(如果我错了希望有人纠正我)。
唯一实用的解决方案是在参数列表中包含函数 ID。
这是接近我想要的修改后的代码。

import pytest


def func_1(x):
    return (x+10)


def func_2(y):
    return (y-10)

func_test_cases = {'func_1': (10, 20, 'func_1'), 'func_2': (10, 3, 'func_2')}


@pytest.mark.parametrize('param, expected, func',
                         func_test_cases.values(),    ids=func_test_cases.keys())
def test(param, expected, func):
    assert eval(func+'(param) == expected')