根据另一个夹具的值参数化一组值

时间:2018-02-15 00:44:01

标签: python pytest

我有一个带有side参数的对象,用于确定对象的行为。我已经为side的有效值创建了一个fixture,以及一个相关的fixture来生成一个用给定值side初始化的对象。

给我带来麻烦的部分是我想测试我的对象在各种整数和字符串上的行为(出于示例目的简化),但我想要传递给我的测试的确切值取决于值side。我目前通过创建列表字典并根据side返回整个列表来实现这一目标,但这并不理想。

示例灯具:

@pytest.fixture(params=['left', 'right'])
def side(request):
    return request.param

@pytest.fixture
def my_obj(side):
    # some object that takes `side` as an arg
    return MyObj(side=side)

@pytest.fixture
def my_ints(side):
    # the ints I want to test depending on `side`
    mapping = {'left': [0, 1, 2], 'right': [11, 22]}
    return mapping[side]

@pytest.fixture
def my_strs(side):
    # the strs I want to test depending on `side`
    mapping = {'left': list('ab'), 'right': list('xyz')}
    return mapping[side]

这里的问题是my_intsmy_strs会返回一个列表,但我想测试列表中的各个值,而不是整个列表。结果,我被迫在测试中使用for循环。

示例测试:

def test_on_ints(my_obj, my_ints):
    for my_int in my_ints:
        # do the same general thing for each my_int
        assert my_obj.some_meth1(my_int) >= 0

def test_on_strs(my_obj, my_strs):
    for my_str in my_strs:
        # do the same general thing for each my_str
        assert 'foo' in my_obj.some_meth2(my_str)

这当然只对side的每个值运行一次测试,给出了以下行的输出:

test_so_example.py::test_on_ints[left] PASSED
test_so_example.py::test_on_ints[right] PASSED
test_so_example.py::test_on_strs[left] PASSED
test_so_example.py::test_on_strs[right] PASSED

理想情况下,我想从测试中删除for循环,并为列表中的每个值运行测试。基本上产生测试输出,如:

test_so_example.py::test_on_ints[left-0] PASSED
test_so_example.py::test_on_ints[left-1] PASSED
test_so_example.py::test_on_ints[left-2] PASSED
test_so_example.py::test_on_ints[right-11] PASSED
test_so_example.py::test_on_ints[right-22] PASSED
(likewise for test_on_strs)

我想做的是什么?是否有不同的结构可以使这更容易?

在实践中,我将通过多次测试来完成此操作,并且侧面有两个以上的值,因此我希望避免明确写出所有(side, int/str/etc)对。

我已经阅读了一些涉及间接参数化的答案,但是没有任何工作可做,也不确定这是否是正确的方法。

1 个答案:

答案 0 :(得分:1)

这可能不是您想要的,但它提供了您想要的测试输出:

test_so_example.py::test_on_ints[left-0] PASSED                                                                                                                                        [ 14%]
test_so_example.py::test_on_ints[left-1] PASSED                                                                                                                                        [ 28%]
test_so_example.py::test_on_ints[left-2] PASSED                                                                                                                                        [ 42%]
test_so_example.py::test_on_ints[right-11] PASSED                                                                                                                                      [ 57%]
test_so_example.py::test_on_ints[right-12] PASSED                                                                                                                                      [ 71%]
test_so_example.py::test_on_strs[left-ab] PASSED                                                                                                                                       [ 85%]
test_so_example.py::test_on_strs[right-xyz] PASSED                                                                                                                                     [100%

结果:

{{1}}