从py.test fixture返回多个对象

Zal*_*lin 13 python unit-testing pytest python-3.x

所以我正在学习如何通过测试简单的事件发射器实现来使用py.test.基本上,它看起来像这样

class EventEmitter():
    def __init__(self):
        ...
    def subscribe(self, event_map):
        # adds listeners to provided in event_map events
    def emit(self, event, *args):
        # emits event with given args
Run Code Online (Sandbox Code Playgroud)

为方便起见,我创建了在测试中使用的Listener类

class Listener():
    def __init__(self):
        ...
    def operation(self):
        # actual listener
Run Code Online (Sandbox Code Playgroud)

目前测试看起来如下

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

def test_emitter(event):
    lstr = event[0]
    ee = event[1]
    ee.emit("event")
    assert lstr.result == 7 # for example
Run Code Online (Sandbox Code Playgroud)

为了测试事件发射器,我需要检查事件传播后监听器的内部状态是否已经改变.因此,我需要两个对象,我不知道是否有更好的方法来做到这一点(也许用两场比赛,而不是一个以某种方式),因为这看起来有点丑我

lmi*_*asf 13

您应该使用称为可迭代解包到变量中的Python 功能。

\n\n
def test_emitter(event):\n    lstr, ee = event # unpacking\n    ee.emit("event")\n    assert lstr.result == 7\n
Run Code Online (Sandbox Code Playgroud)\n\n

基本上,您正在分配event[0]lstrevent[1]ee使用此功能是避免使用索引的一种非常优雅的方法。

\n\n

丢弃

\n\n

如果您要在多个测试中使用固定装置,并且不需要每个测试中的所有值,则如果您不想使用可迭代的某些元素,也可以丢弃它们,如下所示:

\n\n
l = [\'a\', \'b\', \'c\', \'d\']\na, b, c, d = l # unpacking all elements\na, _, c, d = l # discarding b\na, _, _, d = l # python 2: discard b and c\na, *_, d = l # python 3: discard b and c\na, _, _, _ = l # python2: discard, b, c and d\na, *_ = l # python3: discard b, c, and d\n
Run Code Online (Sandbox Code Playgroud)\n\n

理论上,您并不是字面上丢弃这些值,但在 Python 中 _,所谓的 \xe2\x80\x9cI don\xe2\x80\x99t care\xe2\x80\x9d 用于忽略特定值。

\n


Saw*_*wel 7

通常为了避免tuples和美化您的代码,您可以将它们作为一个类重新连接到一个单元,这已经为您完成,使用collections.namedtuple:

import collections
EventListener = collections.namedtuple('EventListener', 'event listener')
Run Code Online (Sandbox Code Playgroud)

现在修改你的夹具:

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

现在修改你的测试:

def test_emitter(event_listener):
 event_listener.event.emit('event')
 assert event_listener.listener.result == 7
Run Code Online (Sandbox Code Playgroud)


Ede*_*eca 5

在这种情况下,您可能需要两个固定装置。

您可以尝试@pytest.yield_fixture类似的操作:

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

@pytest.yield_fixture
def listener(event):
    ...
    yield <listener_properties>
Run Code Online (Sandbox Code Playgroud)

注意:现在已弃用https://docs.pytest.org/en/latest/yieldfixture.html