From a0b60a24cde52b086e5b0fc32affa6de4d1fa165 Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Fri, 13 Dec 2013 12:07:18 -0800 Subject: [PATCH] Option to spew subprocess streams during tests This supersedes PR #4268. Run the tests with '--subproc-streams show' to show output from subprocesses (kernels, IPython.parallel components) in the terminal, or with '--subproc-streams discard' to send it to /dev/null. By default (or with '--subproc-streams capture') the output is piped, captured and displayed only when tests fail. But in some situations, a test fails because of an error which actually occurred earlier, so you have to see all the output. --- IPython/testing/iptest.py | 15 +++++++++++++-- IPython/testing/iptestcontroller.py | 10 ++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/IPython/testing/iptest.py b/IPython/testing/iptest.py index f12e6c41d..a39912a09 100644 --- a/IPython/testing/iptest.py +++ b/IPython/testing/iptest.py @@ -407,14 +407,25 @@ class SubprocessStreamCapturePlugin(Plugin): def __init__(self): Plugin.__init__(self) self.stream_capturer = StreamCapturer() + self.destination = os.environ.get('IPTEST_SUBPROC_STREAMS', 'capture') # This is ugly, but distant parts of the test machinery need to be able # to redirect streams, so we make the object globally accessible. - nose.ipy_stream_capturer = self.stream_capturer + nose.iptest_stdstreams_fileno = self.get_write_fileno + + def get_write_fileno(self): + if self.destination == 'capture': + self.stream_capturer.ensure_started() + return self.stream_capturer.writefd + elif self.destination == 'discard': + return os.open(os.devnull, os.O_WRONLY) + else: + return sys.__stdout__.fileno() def configure(self, options, config): Plugin.configure(self, options, config) # Override nose trying to disable plugin. - self.enabled = True + if self.destination == 'capture': + self.enabled = True def startTest(self, test): # Reset log capture diff --git a/IPython/testing/iptestcontroller.py b/IPython/testing/iptestcontroller.py index 73197c8d2..cea88e80b 100644 --- a/IPython/testing/iptestcontroller.py +++ b/IPython/testing/iptestcontroller.py @@ -237,20 +237,23 @@ def prepare_controllers(options): c_py = [PyTestController(name) for name in py_testgroups] configure_py_controllers(c_py, xunit=options.xunit, - coverage=options.coverage, extra_args=options.extra_args) + coverage=options.coverage, subproc_streams=options.subproc_streams, + extra_args=options.extra_args) controllers = c_py + c_js to_run = [c for c in controllers if c.will_run] not_run = [c for c in controllers if not c.will_run] return to_run, not_run -def configure_py_controllers(controllers, xunit=False, coverage=False, extra_args=()): +def configure_py_controllers(controllers, xunit=False, coverage=False, + subproc_streams='capture', extra_args=()): """Apply options for a collection of TestController objects.""" for controller in controllers: if xunit: controller.add_xunit() if coverage: controller.add_coverage() + controller.env['IPTEST_SUBPROC_STREAMS'] = subproc_streams controller.cmd.extend(extra_args) def do_run(controller): @@ -469,6 +472,9 @@ argparser.add_argument('--xunit', action='store_true', argparser.add_argument('--coverage', nargs='?', const=True, default=False, help="Measure test coverage. Specify 'html' or " "'xml' to get reports.") +argparser.add_argument('--subproc-streams', default='capture', + help="What to do with stdout/stderr from subprocesses. " + "'capture' (default), 'show' and 'discard' are the options.") def default_options(): """Get an argparse Namespace object with the default arguments, to pass to