fix capturing to be more careful during teardown when a setup never happened (due to e.g. an error in user-provided runtest_setup code)

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-12-30 00:11:27 +01:00
parent 77b640d1b7
commit 9d01975c78
3 changed files with 29 additions and 14 deletions

View File

@ -9,6 +9,9 @@ Changes between 1.X and 1.1.1
- new "pytestconfig" funcarg allows access to test config object - new "pytestconfig" funcarg allows access to test config object
- robustify capturing to survive if custom pytest_runtest_setup
code failed and prevented the capturing setup code from running.
- make py.test.* helpers provided by default plugins visible early - - make py.test.* helpers provided by default plugins visible early -
works transparently both for pydoc and for interactive sessions works transparently both for pydoc and for interactive sessions
which will regularly see e.g. py.test.mark and py.test.importorskip. which will regularly see e.g. py.test.mark and py.test.importorskip.

View File

@ -161,16 +161,20 @@ class CaptureManager:
cap.resume() cap.resume()
self._capturing = method self._capturing = method
def suspendcapture(self): def suspendcapture(self, item=None):
self.deactivate_funcargs() self.deactivate_funcargs()
method = self._capturing if hasattr(self, '_capturing'):
if method != "no": method = self._capturing
cap = self._method2capture[method] if method != "no":
outerr = cap.suspend() cap = self._method2capture[method]
else: outerr = cap.suspend()
outerr = "", "" else:
del self._capturing outerr = "", ""
return outerr del self._capturing
if item:
outerr = (item.outerr[0] + outerr[0], item.outerr[1] + outerr[1])
return outerr
return "", ""
def activate_funcargs(self, pyfuncitem): def activate_funcargs(self, pyfuncitem):
if not hasattr(pyfuncitem, 'funcargs'): if not hasattr(pyfuncitem, 'funcargs'):
@ -210,9 +214,6 @@ class CaptureManager:
def pytest_runtest_teardown(self, item): def pytest_runtest_teardown(self, item):
self.resumecapture_item(item) self.resumecapture_item(item)
def pytest_runtest_teardown(self, item):
self.resumecapture_item(item)
def pytest__teardown_final(self, __multicall__, session): def pytest__teardown_final(self, __multicall__, session):
method = self._getmethod(session.config, None) method = self._getmethod(session.config, None)
self.resumecapture(method) self.resumecapture(method)
@ -231,8 +232,7 @@ class CaptureManager:
def pytest_runtest_makereport(self, __multicall__, item, call): def pytest_runtest_makereport(self, __multicall__, item, call):
self.deactivate_funcargs() self.deactivate_funcargs()
rep = __multicall__.execute() rep = __multicall__.execute()
outerr = self.suspendcapture() outerr = self.suspendcapture(item)
outerr = (item.outerr[0] + outerr[0], item.outerr[1] + outerr[1])
if not rep.passed: if not rep.passed:
addouterr(rep, outerr) addouterr(rep, outerr)
if not rep.passed or rep.when == "teardown": if not rep.passed or rep.when == "teardown":

View File

@ -379,3 +379,15 @@ class TestCaptureFuncarg:
]) ])
assert result.ret == 2 assert result.ret == 2
def test_setup_failure_does_not_kill_capturing(testdir):
sub1 = testdir.mkpydir("sub1")
sub1.join("conftest.py").write(py.code.Source("""
def pytest_runtest_setup(item):
raise ValueError(42)
"""))
sub1.join("test_mod.py").write("def test_func1(): pass")
result = testdir.runpytest(testdir.tmpdir, '--traceconfig')
result.stdout.fnmatch_lines([
"*ValueError(42)*",
"*1 error*"
])