From 8f094a719b5792644ffb3c785be2f8177bfcca96 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Sun, 28 Oct 2018 22:44:46 +0000 Subject: [PATCH 1/3] bpo-34945: Buffer output in test suite only when creating junit file After commit d0f49d2f5085ca68e3dc8725f1fb1c9674bfb5ed, the output of the test suite is always buffered as the test output needs to be included in the JUnit file in same cases (as when a test fails). This has the consequence that printing or using debuggers (like pdb) in the test suite does not result in a good user experience anymore. This commit modifies the test suite runner so it only captures the test output when the JUnit file is requested to fix the regression so prints and debuggers are usable again. --- Lib/test/support/__init__.py | 7 +++---- Lib/test/support/testresult.py | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 01e8935cc8d7614..f7a60d4bf2a3cd5 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1921,10 +1921,9 @@ def _filter_suite(suite, pred): def _run_suite(suite): """Run tests from a unittest.TestSuite-derived class.""" - runner = get_test_runner(sys.stdout, verbosity=verbose) - - # TODO: Remove this before merging (here for easy comparison with old impl) - #runner = unittest.TextTestRunner(sys.stdout, verbosity=2, failfast=failfast) + runner = get_test_runner(sys.stdout, + verbosity=verbose, + capture_output=(junit_xml_list is not None)) result = runner.run(suite) diff --git a/Lib/test/support/testresult.py b/Lib/test/support/testresult.py index 8988d3d15278713..f1a31a3c49b5be1 100644 --- a/Lib/test/support/testresult.py +++ b/Lib/test/support/testresult.py @@ -60,10 +60,12 @@ def _add_result(self, test, capture=False, **args): e.set('time', f'{time.perf_counter() - self.__start_time:0.6f}') if capture: - stdout = self._stdout_buffer.getvalue().rstrip() - ET.SubElement(e, 'system-out').text = stdout - stderr = self._stderr_buffer.getvalue().rstrip() - ET.SubElement(e, 'system-err').text = stderr + if self._stdout_buffer: + stdout = self._stdout_buffer.getvalue().rstrip() + ET.SubElement(e, 'system-out').text = stdout + if self._stderr_buffer: + stderr = self._stderr_buffer.getvalue().rstrip() + ET.SubElement(e, 'system-err').text = stderr for k, v in args.items(): if not k or not v: @@ -159,16 +161,16 @@ def run(self, test): test(self.result) return self.result -def get_test_runner_class(verbosity): +def get_test_runner_class(verbosity, buffer=False): if verbosity: return functools.partial(unittest.TextTestRunner, resultclass=RegressionTestResult, - buffer=True, + buffer=buffer, verbosity=verbosity) return QuietRegressionTestRunner -def get_test_runner(stream, verbosity): - return get_test_runner_class(verbosity)(stream) +def get_test_runner(stream, verbosity, capture_output=False): + return get_test_runner_class(verbosity, capture_output)(stream) if __name__ == '__main__': class TestTests(unittest.TestCase): From 832f67382482d9426cfcfd51f1725df2fb73757a Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Mon, 29 Oct 2018 11:12:12 -0400 Subject: [PATCH 2/3] Do not capture output when running without -v as well --- Lib/test/support/testresult.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/test/support/testresult.py b/Lib/test/support/testresult.py index f1a31a3c49b5be1..5eb2e42eaa7ff09 100644 --- a/Lib/test/support/testresult.py +++ b/Lib/test/support/testresult.py @@ -154,8 +154,9 @@ def get_xml_element(self): return e class QuietRegressionTestRunner: - def __init__(self, stream): + def __init__(self, stream, buffer=False): self.result = RegressionTestResult(stream, None, 0) + self.result.buffer = buffer def run(self, test): test(self.result) @@ -167,7 +168,7 @@ def get_test_runner_class(verbosity, buffer=False): resultclass=RegressionTestResult, buffer=buffer, verbosity=verbosity) - return QuietRegressionTestRunner + return functools.partial(QuietRegressionTestRunner, buffer=buffer) def get_test_runner(stream, verbosity, capture_output=False): return get_test_runner_class(verbosity, capture_output)(stream) From 27d25d61531df678a111b61c396d48761582607d Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Mon, 29 Oct 2018 15:50:34 -0400 Subject: [PATCH 3/3] Check for identity on None --- Lib/test/support/testresult.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/support/testresult.py b/Lib/test/support/testresult.py index 5eb2e42eaa7ff09..67e126dcf7527ab 100644 --- a/Lib/test/support/testresult.py +++ b/Lib/test/support/testresult.py @@ -60,10 +60,10 @@ def _add_result(self, test, capture=False, **args): e.set('time', f'{time.perf_counter() - self.__start_time:0.6f}') if capture: - if self._stdout_buffer: + if self._stdout_buffer is not None: stdout = self._stdout_buffer.getvalue().rstrip() ET.SubElement(e, 'system-out').text = stdout - if self._stderr_buffer: + if self._stderr_buffer is not None: stderr = self._stderr_buffer.getvalue().rstrip() ET.SubElement(e, 'system-err').text = stderr