introduce and document "session" scope for finalization helpers

--HG--
branch : trunk
This commit is contained in:
holger krekel
2009-05-21 14:37:30 +02:00
parent b8c3f866b5
commit 5d3a3add83
5 changed files with 70 additions and 25 deletions

View File

@@ -148,6 +148,8 @@ class FuncargRequest:
return self._pyfuncitem
elif scope == "module":
return self._pyfuncitem.getparent(py.test.collect.Module)
elif scope == "session":
return None
raise ValueError("unknown finalization scope %r" %(scope,))
def addfinalizer(self, finalizer, scope="function"):

View File

@@ -175,29 +175,37 @@ class SetupState(object):
self._finalizers = {}
def addfinalizer(self, finalizer, colitem):
""" attach a finalizer to the given colitem.
if colitem is None, this will add a finalizer that
is called at the end of teardown_all().
"""
assert callable(finalizer)
#assert colitem in self.stack
self._finalizers.setdefault(colitem, []).append(finalizer)
def _teardown(self, colitem):
def _pop_and_teardown(self):
colitem = self.stack.pop()
self._teardown_with_finalization(colitem)
def _teardown_with_finalization(self, colitem):
finalizers = self._finalizers.pop(colitem, None)
while finalizers:
fin = finalizers.pop()
fin()
colitem.teardown()
if colitem:
colitem.teardown()
for colitem in self._finalizers:
assert colitem in self.stack
assert colitem is None or colitem in self.stack
def teardown_all(self):
while self.stack:
col = self.stack.pop()
self._teardown(col)
self._pop_and_teardown()
self._teardown_with_finalization(None)
assert not self._finalizers
def teardown_exact(self, item):
if self.stack and self.stack[-1] == item:
col = self.stack.pop()
self._teardown(col)
assert self.stack and self.stack[-1] == item
self._pop_and_teardown()
def prepare(self, colitem):
""" setup objects along the collector chain to the test-method
@@ -206,8 +214,7 @@ class SetupState(object):
while self.stack:
if self.stack == needed_collectors[:len(self.stack)]:
break
col = self.stack.pop()
self._teardown(col)
self._pop_and_teardown()
for col in needed_collectors[len(self.stack):]:
col.setup()
self.stack.append(col)

View File

@@ -147,17 +147,36 @@ class TestRequest:
req._fillfuncargs()
assert item.funcargs == {'something': 1}
def test_request_addfinalizer(self, testdir):
def test_request_addfinalizer_scopes(self, testdir):
item = testdir.getitem("""
def pytest_funcarg__something(request): pass
teardownlist = []
def pytest_funcarg__something(request):
for scope in ("function", "module", "session"):
request.addfinalizer(
lambda x=scope: teardownlist.append(x),
scope=scope)
def test_func(something): pass
""")
req = funcargs.FuncargRequest(item)
req.config._setupstate.prepare(item) # XXX
req._fillfuncargs()
# successively check finalization calls
teardownlist = item.getparent(py.test.collect.Module).obj.teardownlist
ss = item.config._setupstate
assert not teardownlist
ss.teardown_exact(item)
print ss.stack
assert teardownlist == ['function']
ss.teardown_exact(item.parent)
assert teardownlist == ['function', 'module']
ss.teardown_all()
assert teardownlist == ['function', 'module', 'session']
def test_request_addfinalizer_unknown_scope(self, testdir):
item = testdir.getitem("def test_func(): pass")
req = funcargs.FuncargRequest(item)
py.test.raises(ValueError, "req.addfinalizer(None, scope='xyz')")
l = [1]
req.addfinalizer(l.pop)
req.config._setupstate._teardown(item)
assert not l
def test_request_getmodulepath(self, testdir):
modcol = testdir.getmodulecol("def test_somefunc(): pass")

View File

@@ -6,8 +6,24 @@ class TestSetupState:
ss = SetupState()
item = testdir.getitem("def test_func(): pass")
l = [1]
ss.prepare(item)
ss.addfinalizer(l.pop, colitem=item)
ss._teardown(item)
assert l
ss._pop_and_teardown()
assert not l
def test_setup_scope_None(self, testdir):
item = testdir.getitem("def test_func(): pass")
ss = SetupState()
l = [1]
ss.prepare(item)
ss.addfinalizer(l.pop, colitem=None)
assert l
ss._pop_and_teardown()
assert l
ss._pop_and_teardown()
assert l
ss.teardown_all()
assert not l
class TestSetupStateFunctional: