Skip to content

Suggestion: merge .fixture and .yield_fixture #1461

Closed
@csaftoiu

Description

@csaftoiu

The yield_fixture page says:

lastly yield introduces more than one way to write fixture functions, so what’s the obvious way to a newcomer?

My suggestion is to merge pytest.fixture and pytest.yield_fixture.

Before:

@pytest.fixture
def foo():
    return ['bar']

@pytest.yield_fixture
def boof():
    with some_stuff as more_stuff:
        yield even_more_stuff(more_stuff)

After:

@pytest.fixture
def foo():
    return ['bar']

@pytest.fixture
def boof():
    with some_stuff as more_stuff:
        yield even_more_stuff(more_stuff)

This should be possible - if calling the fixture function returns a generator, then do what yield_fixture currently does, otherwise (i.e. if it returns a value), then do what fixture currently does.

The reason? There will be one less choice for a newcomer to make - which decorator to call.


Further, the documentation section "Fixture finalization / executing teardown code" can now read something like this:

pytest supports execution of fixture specific finalization code when the fixture goes out of scope. By yielding the fixture object instead of returning it, you can perform finalization code after the test has finished executing:

# content of conftest.py

import smtplib
import pytest

@pytest.fixture(scope="module")
def smtp(request):
    smtp = smtplib.SMTP("smtp.gmail.com")
    yield smtp  # provide the fixture value
    print("teardown smtp")
    smtp.close()

The code after the yieldwill execute when the last test using the fixture in the module has finished execution.

This is a straightforward change, syntactically (return -> yield), even if the internals are quite different, and is intuitive enough to me, and I suspect anyone who gets how generators work.

I suggest deprecating the old callback-teardown method since the yield mechanism is superior in every way. Really it should be the only way, but it may be confusing to someone who expects to be able to simply return a value, and so returning a value will just work as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: proposalproposal for a new feature, often to gather opinions or design the API around the new feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions