2013-04-04 128 views
5

密切相關的:In python, is there a good idiom for using context managers in setup/teardownpy.test - 如何使用上下文管理器在funcarg /夾具


我有一個在測試中使用固定的時間/時區上下文管理。我想要一個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) 

...但它有點噁心。在相關的Q jsbueno中指出:問題是如果發生異常,代碼沒有規定可以正確調用對象的__exit__方法。

His answer使用元類方法。但是這對於pytest來說並不是那麼有用,在pytest中,測試通常只是函數,而不是類。那麼解決這個問題的最好方法是什麼?涉及runtest hooks的內容?

回答

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__()調用發生。

+1

我擔心的不是'__exit__'不能被調用,但它不會被[右值]調用(http://docs.python.org/2/reference/datamodel的.html#上下文經理)。 '__exit__'通常被調用,其值與'with'塊中提出的任何異常有關(或者在這種情況下它將是測試主體)。 – pfctdayelise 2013-04-05 01:19:02

9

由於2.4,py.testyield款式夾具支持。我們可以直接在其內部使用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() 
+0

我認爲屈服風格的裝置已被棄用? – 2016-08-25 17:22:54

+1

@NeilG感謝您的評論。我更新了pytest 3.0更改的答案。 – 2016-08-26 04:55:01

相關問題