py.test - 如何在funcarg / fixture中使用上下文管理器

时间:2013-04-04 02:43:49

标签: pytest contextmanager

密切相关: In python, is there a good idiom for using context managers in setup/teardown


我有一个上下文管理器,用于测试以修复时间/时区。我想把它放在pytest funcarg(或夹具中,我们正在使用pytest 2.2.3但我可以向后翻译)。我可以这样做:

def pytest_funcarg__fixedTimezone(request):
    # fix timezone to match Qld, no DST to worry about and matches all
    # Eastern states in winter.
    fixedTime = offsetTime.DisplacedRealTime(tz=' Australia/Brisbane')

    def setup():
        fixedTime.__enter__()
        return fixedTime

    def teardown(fixedTime):
        # this seems rather odd?
        fixedTime.__exit__(None, None, None)

......但它有点icky。在相关的Q jsbueno中指出:问题是,如果发生异常,您的代码无法正确调用对象的__exit__方法。

His answer使用元类方法。但这对pytest来说并不是那么有用,因为pytest通常只是函数,而不是类。那么解决这个问题的方法是什么?涉及runtest hooks的事情?

2 个答案:

答案 0 :(得分:13)

从2.4开始,py.test具有yield样式夹具支持。我们可以直接在其中使用with上下文。

@pytest.yield_fixture
def passwd():
    with open("/etc/passwd") as f:
        yield f.readlines()

自3.0以来,py.test弃用@pytest.yield_fixture用法。我们可以直接使用@pytest.fixture作为上下文管理器。

@pytest.fixture
def passwd():
    with open("/etc/passwd") as f:
        yield f.readlines()

答案 1 :(得分:0)

我担心目前没有优雅的方法在灯具中使用上下文管理器。但是,如果测试失败,终结器将会运行:

import contextlib, pytest

@contextlib.contextmanager
def manager():
    print 'manager enter'
    yield 42
    print 'manager exit'

@pytest.fixture
def fix(request):
    m = manager()
    request.addfinalizer(lambda: m.__exit__(None, None, None))
    return m.__enter__()

def test_foo(fix):
    print fix
    raise Exception('oops')

如果您使用pytest -s运行此操作,则会看到__exit__()来电。{/ p>