4

In my unit tests, I have two very similar fixtures, and I was hoping to break out some of the functionality into a helper function of some kind. Given my understanding of how yield produces generators, I don't feel like this should cause any kind of problem. my_fixture_with_helper, should just return the generator that fixture_helper produces.

import pytest


def fixture_helper():
    print("Initialized from the helper...")
    yield 26
    print("Tearing down after the helper...")


@pytest.fixture
def my_fixture_with_helper():
    return fixture_helper()


@pytest.fixture
def my_fixture():
    print("Initialized from the fixture...")
    yield 26
    print("Tearing down after the fixture...")


def test_nohelper(my_fixture):
    pass


def test_helper(my_fixture_with_helper):
    pass

However, if I run pytest --capture=no, I get the following

test_foo.py Initialized from the fixture...
.Tearing down after the fixture...
.

I would expect "Initialized from the helper" and "Tearing down after the helper" to get printed, but it does not, and I cannot figure out why. Why does this not work?

ollien
  • 4,418
  • 9
  • 35
  • 58

1 Answers1

8

You need to use yield from to be able to pass the generator through properly. Otherwise the generator object will be returned, which isn't recognized by pytest as a generator.

@pytest.fixture
def my_fixture_with_helper():
    yield from fixture_helper()

Much more information about yield from can be found at this stackoverflow post.

Marcus
  • 3,216
  • 2
  • 22
  • 22
  • Why would it not be recognizable? Doesn't yield normally return a generator? – ollien Feb 05 '19 at 19:29
  • Aha! My version doesn't allow pytest to understand that it's a generator function (see `inspect.isgeneratorfunction`) Thank you! – ollien Feb 05 '19 at 20:00