Returning multiple objects from a pytest fixture

You will probably need two fixtures in this case.

You can try the @pytest.yield_fixture like:

@pytest.yield_fixture
def event():
    ...
    yield <event_properties>

@pytest.yield_fixture
def listener(event):
    ...
    yield <listener_properties>

Note: this is now deprecated https://docs.pytest.org/en/latest/yieldfixture.html


You should use a Python feature called iterable unpacking into variables.

def test_emitter(event):
    lstr, ee = event # unpacking
    ee.emit("event")
    assert lstr.result == 7

Basically, you are assigning event[0] to lstr, and event[1] to ee. Using this feature is a very elegant way to avoid using indexes.

Discarding

In case you are going to use your fixture in mutiple tests, and you don't need all values in every test, you can also discard some elements of the iterable if you are not interested in using them as follows:

l = ['a', 'b', 'c', 'd']
a, b, c, d = l # unpacking all elements
a, _, c, d = l # discarding b
a, _, _, d = l # python 2: discard b and c
a, *_, d = l # python 3: discard b and c
a, _, _, _ = l # python2: discard, b, c and d
a, *_ = l # python3: discard b, c, and d

In theory, you are not literally discarding the values, but in Python _, so-called “I don’t care”, is used for ignoring the specific values.


If you can not afford to easily split your tuple fixture into two independent fixtures, you can now "unpack" a tuple or list fixture into other fixtures using my pytest-cases plugin as explained in this answer.

For your example that would look like:

from pytest_cases import pytest_fixture_plus

@pytest_fixture_plus(unpack_into="lstr,ee")
def event():
    ee = EventEmitter()
    lstr = Listener()
    ee.subscribe({"event" : [lstr.operation]})
    return lstr, ee

def test_emitter(lstr, ee):
    ee.emit("event")
    assert lstr.result == 7 # for example

Usually in order to avoid tuples and beautify your code, you can join them back together to one unit as a class, which has been done for you, using collections.namedtuple:

import collections
EventListener = collections.namedtuple('EventListener', 'event listener')

Now modify your fixture:

@pytest.fixture
def event_listener():
 e = EventListener(EventEmitter(), Listener())
 e.event.subscribe({'event' : [e.listener.operation]})
 return e

Now modify your test:

def test_emitter(event_listener):
 event_listener.event.emit('event')
 assert event_listener.listener.result == 7