diff --git a/py/io/stdcapture.py b/py/io/stdcapture.py index 40a6e3175..2c4bd376c 100644 --- a/py/io/stdcapture.py +++ b/py/io/stdcapture.py @@ -22,14 +22,14 @@ class Capture(object): call = classmethod(call) def reset(self): - """ reset sys.stdout and sys.stderr - - returns a tuple of file objects (out, err) for the captured - data + """ reset sys.stdout and sys.stderr and return captured output + as strings and restore sys.stdout/err. """ - outfile, errfile = self.done() - return outfile.read(), errfile.read() - + x, y = self.done() + outerr = x.read(), y.read() + x.close() + y.close() + return outerr class StdCaptureFD(Capture): """ This class allows to capture writes to FD1 and FD2 @@ -58,11 +58,14 @@ class StdCaptureFD(Capture): def done(self): """ return (outfile, errfile) and stop capturing. """ - outfile = errfile = emptyfile if hasattr(self, 'out'): outfile = self.out.done() + else: + outfile = StringIO() if hasattr(self, 'err'): errfile = self.err.done() + else: + errfile = StringIO() if hasattr(self, '_oldin'): oldsys, oldfd = self._oldin os.dup2(oldfd, 0) @@ -94,15 +97,9 @@ class StdCapture(Capture): self.oldin = sys.stdin sys.stdin = self.newin = DontReadFromInput() - def reset(self): - """ return captured output as strings and restore sys.stdout/err.""" - x, y = self.done() - return x.read(), y.read() - def done(self): """ return (outfile, errfile) and stop capturing. """ o,e = sys.stdout, sys.stderr - outfile = errfile = emptyfile if self._out: try: sys.stdout = self.oldout @@ -111,6 +108,8 @@ class StdCapture(Capture): del self.oldout outfile = self.newout outfile.seek(0) + else: + outfile = StringIO() if self._err: try: sys.stderr = self.olderr @@ -119,6 +118,8 @@ class StdCapture(Capture): del self.olderr errfile = self.newerr errfile.seek(0) + else: + errfile = StringIO() if self._in: sys.stdin = self.oldin return outfile, errfile @@ -144,5 +145,4 @@ except AttributeError: else: devnullpath = '/dev/null' -emptyfile = StringIO() diff --git a/py/test/plugin/pytest_runner.py b/py/test/plugin/pytest_runner.py index f6c31337a..62404084a 100644 --- a/py/test/plugin/pytest_runner.py +++ b/py/test/plugin/pytest_runner.py @@ -61,11 +61,7 @@ def pytest_runtest_call(item): item.runtest() def pytest_runtest_makereport(item, call): - if isinstance(call, str): - # crashed item - return ItemTestReport(item, excinfo=call, when="???") - else: - return ItemTestReport(item, call.excinfo, call.when, call.outerr) + return ItemTestReport(item, call.excinfo, call.when, call.outerr) def pytest_runtest_teardown(item): item.config._setupstate.teardown_exact(item) @@ -101,10 +97,15 @@ class RuntestHookCall: self.outerr = capture.reset() def forked_run_report(item): + # for now, we run setup/teardown in the subprocess + # XXX optionally allow sharing of setup/teardown EXITSTATUS_TESTEXIT = 4 from py.__.test.dist.mypickle import ImmutablePickler ipickle = ImmutablePickler(uneven=0) ipickle.selfmemoize(item.config) + # XXX workaround the issue that 2.6 cannot pickle + # instances of classes defined in global conftest.py files + ipickle.selfmemoize(item) def runforked(): try: reports = runtestprotocol(item, log=False)