当灯具具有相同参数时如何使用间接参数化?

Int*_*rer 5 python pytest

我正在使用pytest的间接参数化来参数化上游设备。这对我来说一直很好。

但是,现在当上游设备具有相同的参数名称时,我被困住了,并且我想向它们传递不同的值。

当要参数化的上游设备的参数名称相同时,如何使用间接参数化?


示例代码

import pytest

class Config:
    """This is a configuration object."""
    def __init__(self, a: int, b: int):
        self._a = a
        self._b = b

@pytest.fixture
def config(a: int, b: int) -> Config:
    return Config(a, b)

class Foo:
    def __init__(self, config: Config):
        """This does some behavior."""
        self.config = config

@pytest.fixture
def foo(config: Config) -> Foo:
    return Foo(config)

class Bar:
    def __init__(self, config: Config):
        """This does some other behavior."""
        self.config = config

@pytest.fixture
def bar(config: Config) -> Bar:
    return Bar(config)

class TestFooBarTogether:
    @pytest.mark.parametrize("a, b", [(1, 2)])
    def test_foo_alone(self, foo: Foo) -> None:
        """This works fine, since parameters get passed all the way to Config."""

    @pytest.mark.parametrize("a, b", [(1, 2)])
    def test_together(self, foo: Foo, bar: Bar) -> None:
        """Test interactions between the two objects.

        This does not work, because both foo and bar get the same config.
        How can I pass a different config to foo and bar, even though Config
        takes both an "a" and a "b"?
        
        I would like to pass `foo` something like (1, 2) and 
        `bar` something like (3, 4).

        """
Run Code Online (Sandbox Code Playgroud)

hoe*_*ing 3

更新

config在对两者foobar不同实例进行参数化时,我没有看到使用夹具的选项Config。放弃夹具并间接config参数化,我得出:foobar

@pytest.fixture
def foo(request) -> Foo:
    return Foo(Config(*request.param))


@pytest.fixture
def bar(request) -> Bar:
    return Bar(Config(*request.param))


@pytest.mark.parametrize("foo", [(1, 2)], indirect=True)
def test_foo_alone(foo: Foo) -> None:
    assert foo.config._a == 1
    assert foo.config._b == 2


@pytest.mark.parametrize("foo,bar", [((1, 2), (3, 4))], indirect=True)
def test_together(foo: Foo, bar: Bar) -> None:
    assert foo.config._a == 1
    assert foo.config._b == 2
    assert bar.config._a == 3
    assert bar.config._b == 4
Run Code Online (Sandbox Code Playgroud)

config在我看来,期望a和参数化的装置b无论如何都不适合这里,因为它预计会在每次调用时被称为 new ,就像通常的函数一样 - 我只是使用Config构造函数来代替。

原答案

如果您需要确保每次调用时都有新对象,您可以随时切换到工厂装置config。和args 被封装在工厂中,a因此b不需要拖拽它们。

ConfigFactory = Callable[[], Config]

@pytest.fixture
def config(a: int, b: int) -> ConfigFactory:
    return lambda: Config(a, b)


@pytest.fixture
def foo(config: ConfigFactory) -> Foo:
    return Foo(config())


@pytest.fixture
def bar(config: ConfigFactory) -> Bar:
    return Bar(config())


@pytest.mark.parametrize("a, b", [(1, 2)])
def test_together(foo: Foo, bar: Bar) -> None:
    assert not foo.config == bar.config
Run Code Online (Sandbox Code Playgroud)