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

pfc*_*ise 8 contextmanager pytest

密切相关: 在python中,在setup/teardown中使用上下文管理器是否有一个很好的习惯用法


我有一个上下文管理器,用于测试以修复时间/时区.我想把它放在pytest funcarg(或夹具中,我们使用pytest2.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)
Run Code Online (Sandbox Code Playgroud)

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

他的回答使用了元类方法.但这对pytest来说并不是那么有用,因为pytest通常只是函数,而不是类.那么解决这个问题的方法是什么?什么涉及测试钩

Jia*_*ang 14

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

@pytest.yield_fixture
def passwd():
    with open("/etc/passwd") as f:
        yield f.readlines()
Run Code Online (Sandbox Code Playgroud)

从3.0开始,py.test不推荐@pytest.yield_fixture使用.我们可以@pytest.fixture直接用作上下文管理器.

@pytest.fixture
def passwd():
    with open("/etc/passwd") as f:
        yield f.readlines()
Run Code Online (Sandbox Code Playgroud)


flu*_*lub 1

恐怕目前还没有在装置中使用上下文管理器的优雅方法。但是,如果测试失败,终结器将运行:

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')
Run Code Online (Sandbox Code Playgroud)

如果您运行此命令,pytest -s您将看到调用__exit__()发生。