pytest:如何在多个测试函数之间共享参数化的参数

时间:2018-08-08 06:03:56

标签: pytest

我在同一文件中有许多测试函数,它们共享一组通用的参数化参数,如下面的代码片段所示。当测试功能的数量增加(> 100)时,为每个测试功能重复这些参数似乎并不有效,并且容易出错。 pytest中有什么方法可以定义一组通用的参数化参数并在所有测试中共享?夹具用于注入公共数据依赖项。我想知道是否有任何类似的工具可以注入常见的 arguments

import pytest

@pytest.mark.parametrize('common_arg1', [0, 1])
@pytest.mark.parametrize('common_arg2', [2, 3])
@pytest.mark.parametrize('a', [0, 1])
def test_1(common_arg1, common_arg2, a):
    pass

@pytest.mark.parametrize('common_arg1', [0, 1])  # repetition
@pytest.mark.parametrize('common_arg2', [2, 3])  # repetition
@pytest.mark.parametrize('b', [0, 1])
def test_2(common_arg1, common_arg2, b):
    pass

...

@pytest.mark.parametrize('common_arg1', [0, 1])  # more repetition!
@pytest.mark.parametrize('common_arg2', [2, 3])  # more repetition!
@pytest.mark.parametrize('x', [0, 1])
def test_100(common_arg1, common_arg2, x):
    pass

3 个答案:

答案 0 :(得分:2)

您可以将所有测试用例移到一个帮助器类中,并将通用装饰器放在该类的顶部。某些测试(方法)专用的装饰器可以直接应用于它们。请查看下面的示例。

import pytest


@pytest.mark.parametrize('common_arg1', [0, 1])
@pytest.mark.parametrize('common_arg2', [2, 3])
class TestParametrized:

    @pytest.mark.parametrize('a', [0, 1])
    def test_1(self, common_arg1, common_arg2, a):
        pass

    @pytest.mark.parametrize('b', [0, 1])
    def test_2(self, common_arg1, common_arg2, b):
        pass

    @pytest.mark.parametrize('x', [0, 1])
    def test_100(self, common_arg1, common_arg2, x):
        pass

答案 1 :(得分:1)

正如Kammil指出的那样,最好的方法是拥有一个Test类,作为Kammil方法的替代方法,是在您的测试数据中拥有一个class属性,通过这种方式,您可以拥有不使用common_arg1的测试方法。和class中的common_arg2。但是,您仍然需要标记测试,但不需要重写所有参数化参数,并且如果您从class属性更改值,那么它将反映在所有测试中。

如果要在同一类中使用不需要common_arg1和common_arg2的测试方法,这将特别有用。

请记住,如果您装饰类,则所有方法都必须具有common_arg1和common_arg2作为参数,如果您尝试编写一个不在方法的args列表中引用它们的方法,则将得到一个{{1} }错误。

为避免这种情况,您可以执行以下操作:

function uses no argument 'common_arg1'

请注意,test_1000将成功执行,并且不会抱怨没有提到common_args1和common_args2。您还可以通过编写两个类属性将common_args拆分为2。

答案 2 :(得分:0)

另一种方法是使用参数化的 pytest 固定装置。对于单个参数化,很容易使用普通的 pytest:

import pytest

@pytest.fixture(params=[0, 1])
def common_arg1(request):
    return request.param

@pytest.fixture(params=[2, 3])
def common_arg2(request):
    return request.param

@pytest.mark.parametrize('a', [0, 1])
def test_1(common_arg1, common_arg2, a):
    pass

@pytest.mark.parametrize('b', [0, 1])
def test_2(common_arg1, common_arg2, b):
    pass

@pytest.mark.parametrize('x', [0, 1])
def test_100(common_arg1, common_arg2, x):
    pass

如果您希望以更紧凑的方式编写此代码,可以使用 pytest_cases.param_fixture

from pytest_cases import param_fixture

common_arg1 = param_fixture('common_arg1', [0, 1])
common_arg2 = param_fixture('common_arg2', [2, 3])

对于多个参数化,您可能希望使用 @pytest_cases.fixture 以便能够使用 @pytest.mark.parametrize

import pytest
from pytest_cases import fixture

@fixture
@pytest.mark.parametrize('a', [0, 1])
@pytest.mark.parametrize('b', [2, 3])
def common_arg_multiple(a, b):
    return a * b, a - b

有关详细信息,请参阅 pytest-cases documentation。 (我是作者;))