Skip to content

Per-use fixture scope #2833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dmtucker opened this issue Oct 12, 2017 · 5 comments
Closed

Per-use fixture scope #2833

dmtucker opened this issue Oct 12, 2017 · 5 comments
Labels
topic: fixtures anything involving fixtures directly or indirectly type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature

Comments

@dmtucker
Copy link

dmtucker commented Oct 12, 2017

I often find myself needing 2 results from a function-scoped fixture for the same test run.

To do this today, I need a factory:

@pytest.fixture
def foo_factory(a, b, c, d_factory):
    def _foo():
        d = d_factory()
        # Use a, b, c, and d to make foo.
        return foo
    return _foo


@pytest.fixture
def bar(foo_factory):
    foo = foo_factory()
    # Use foo to make some_bar.
    return some_bar


@pytest.fixture
def baz(bar, foo_factory):
    foo = foo_factory()
    # Use foo and bar to make some_baz.
    return some_baz


def test_baz(baz):
    assert baz.whatever

Alternatively, I can invoke foo directly (like a regular function), but then everything foo accepts (i.e. a, b, c, d) must be defined in the calling scope which is unscalable.

If there was, say, a 'call' scope, this could be replaced with:

@pytest.fixture(scope='call')
def foo(a, b, c, d):  # d would also be call-scoped.
    # Use a, b, c, and d to make some_foo.
    return some_foo


# A function-scoped fixture would not be able to depend on a call-scoped fixture.
@pytest.fixture(scope='call')
def bar(foo):
    # Use foo to make some_bar.
    return some_bar


@pytest.fixture(scope='call')
def baz(foo, bar):
    # Use foo and bar to make some_baz.
    return some_baz


def test_baz(baz):
    assert baz.whatever
  • Note that bar and baz get distinct foos.

In other words, this is a feature request for a fixture scope that behaves just like regular function invocations, but you don't have to do the invocation, pytest does it for you (which keeps the calling scope uncluttered).

@nicoddemus nicoddemus added the type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature label Oct 19, 2017
@nicoddemus
Copy link
Member

I'm personally -1 on this, I think the factory option is good enough to implement and understand. Adding it as yet another fixture flavor option to pytest would only bring more complexity for little benefit, IMHO.

@RonnyPfannschmidt
Copy link
Member

a subrequest scope was under discussion before and i like it

however as of now this cant be sanely implemented

@dmtucker
Copy link
Author

dmtucker commented Apr 4, 2018

Possible dupe: #456

Another data point: using a factory prevents pretty-parameter failure output.
For example, an error in bar would not expose the value of foo:

______________________________ ERROR at setup of test_baz ______________________________

foo_factory = <function foo_factory at 0x7f76ce36f140>

@nicoddemus
Copy link
Member

Ref: #2703

@asottile
Copy link
Member

Duplicate of #456 I believe, if not feel free to reopen (let's consolidate discussion on this there)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: fixtures anything involving fixtures directly or indirectly type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature
Projects
None yet
Development

No branches or pull requests

5 participants