From 9e565386d3fafc8cc15d07095e50d574e5f53802 Mon Sep 17 00:00:00 2001 From: Baptiste Mispelon Date: Sat, 30 Nov 2019 22:10:16 +0100 Subject: [PATCH] Fixed #27430 -- Added -b/--buffer option to DiscoverRunner. --- django/test/runner.py | 13 +++++++- docs/ref/django-admin.txt | 7 +++++ docs/releases/3.1.txt | 3 ++ tests/runtests.py | 9 ++++-- tests/test_runner/test_discover_runner.py | 30 ++++++++++++++++++- tests/test_runner_apps/buffer/tests_buffer.py | 14 +++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/test_runner_apps/buffer/tests_buffer.py diff --git a/django/test/runner.py b/django/test/runner.py index 194077d81a..ff124064db 100644 --- a/django/test/runner.py +++ b/django/test/runner.py @@ -434,7 +434,7 @@ class DiscoverRunner: interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, parallel=0, tags=None, exclude_tags=None, test_name_patterns=None, - pdb=False, **kwargs): + pdb=False, buffer=False, **kwargs): self.pattern = pattern self.top_level = top_level @@ -451,6 +451,12 @@ class DiscoverRunner: self.pdb = pdb if self.pdb and self.parallel > 1: raise ValueError('You cannot use --pdb with parallel tests; pass --parallel=1 to use it.') + self.buffer = buffer + if self.buffer and self.parallel > 1: + raise ValueError( + 'You cannot use -b/--buffer with parallel tests; pass ' + '--parallel=1 to use it.' + ) self.test_name_patterns = None if test_name_patterns: # unittest does not export the _convert_select_pattern function @@ -503,6 +509,10 @@ class DiscoverRunner: '--pdb', action='store_true', help='Runs a debugger (pdb, or ipdb if installed) on error or failure.' ) + parser.add_argument( + '-b', '--buffer', action='store_true', + help='Discard output from passing tests.', + ) if PY37: parser.add_argument( '-k', action='append', dest='test_name_patterns', @@ -617,6 +627,7 @@ class DiscoverRunner: 'failfast': self.failfast, 'resultclass': self.get_resultclass(), 'verbosity': self.verbosity, + 'buffer': self.buffer, } def run_checks(self): diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 58fb34e821..cbb4a2d8ed 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -1462,6 +1462,13 @@ Runs test methods and classes matching test name patterns, in the same way as Spawns a ``pdb`` debugger at each test error or failure. If you have it installed, ``ipdb`` is used instead. +.. django-admin-option:: --buffer, -b + +.. versionadded:: 3.1 + +Discards output (``stdout`` and ``stderr``) for passing tests, in the same way +as :option:`unittest's --buffer option`. + ``testserver`` -------------- diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt index ae266e877d..7ae21330a6 100644 --- a/docs/releases/3.1.txt +++ b/docs/releases/3.1.txt @@ -257,6 +257,9 @@ Tests * The new :setting:`MIGRATE ` test database setting allows disabling of migrations during a test database creation. +* Django test runner now supports a :option:`test --buffer` option to discard + output for passing tests. + URLs ~~~~ diff --git a/tests/runtests.py b/tests/runtests.py index 293396f96c..1282538a6d 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -281,7 +281,7 @@ class ActionSelenium(argparse.Action): def django_tests(verbosity, interactive, failfast, keepdb, reverse, test_labels, debug_sql, parallel, tags, exclude_tags, - test_name_patterns, start_at, start_after, pdb): + test_name_patterns, start_at, start_after, pdb, buffer): state = setup(verbosity, test_labels, parallel, start_at, start_after) extra_tests = [] @@ -302,6 +302,7 @@ def django_tests(verbosity, interactive, failfast, keepdb, reverse, exclude_tags=exclude_tags, test_name_patterns=test_name_patterns, pdb=pdb, + buffer=buffer, ) failures = test_runner.run_tests( test_labels or get_installed(), @@ -497,6 +498,10 @@ if __name__ == "__main__": '--pdb', action='store_true', help='Runs the PDB debugger on error or failure.' ) + parser.add_argument( + '-b', '--buffer', action='store_true', + help='Discard output of passing tests.', + ) if PY37: parser.add_argument( '-k', dest='test_name_patterns', action='append', @@ -563,7 +568,7 @@ if __name__ == "__main__": options.debug_sql, options.parallel, options.tags, options.exclude_tags, getattr(options, 'test_name_patterns', None), - options.start_at, options.start_after, options.pdb, + options.start_at, options.start_after, options.pdb, options.buffer, ) if failures: sys.exit(1) diff --git a/tests/test_runner/test_discover_runner.py b/tests/test_runner/test_discover_runner.py index 2334fe6b7f..186dc52a44 100644 --- a/tests/test_runner/test_discover_runner.py +++ b/tests/test_runner/test_discover_runner.py @@ -6,7 +6,7 @@ from unittest import TestSuite, TextTestRunner, defaultTestLoader, skipUnless from django.db import connections from django.test import SimpleTestCase from django.test.runner import DiscoverRunner -from django.test.utils import captured_stdout +from django.test.utils import captured_stderr, captured_stdout from django.utils.version import PY37 @@ -269,6 +269,34 @@ class DiscoverRunnerTests(SimpleTestCase): with self.assertRaisesMessage(ValueError, msg): DiscoverRunner(pdb=True, parallel=2) + def test_buffer_with_parallel(self): + msg = ( + 'You cannot use -b/--buffer with parallel tests; pass ' + '--parallel=1 to use it.' + ) + with self.assertRaisesMessage(ValueError, msg): + DiscoverRunner(buffer=True, parallel=2) + + def test_buffer_mode_test_pass(self): + runner = DiscoverRunner(buffer=True, verbose=0) + with captured_stdout() as stdout, captured_stderr() as stderr: + suite = runner.build_suite([ + 'test_runner_apps.buffer.tests_buffer.WriteToStdoutStderrTestCase.test_pass', + ]) + runner.run_suite(suite) + self.assertNotIn('Write to stderr.', stderr.getvalue()) + self.assertNotIn('Write to stdout.', stdout.getvalue()) + + def test_buffer_mode_test_fail(self): + runner = DiscoverRunner(buffer=True, verbose=0) + with captured_stdout() as stdout, captured_stderr() as stderr: + suite = runner.build_suite([ + 'test_runner_apps.buffer.tests_buffer.WriteToStdoutStderrTestCase.test_fail', + ]) + runner.run_suite(suite) + self.assertIn('Write to stderr.', stderr.getvalue()) + self.assertIn('Write to stdout.', stdout.getvalue()) + class DiscoverRunnerGetDatabasesTests(SimpleTestCase): runner = DiscoverRunner(verbosity=2) diff --git a/tests/test_runner_apps/buffer/tests_buffer.py b/tests/test_runner_apps/buffer/tests_buffer.py new file mode 100644 index 0000000000..36bc315d6d --- /dev/null +++ b/tests/test_runner_apps/buffer/tests_buffer.py @@ -0,0 +1,14 @@ +import sys +from unittest import TestCase + + +class WriteToStdoutStderrTestCase(TestCase): + def test_pass(self): + sys.stderr.write('Write to stderr.') + sys.stdout.write('Write to stdout.') + self.assertTrue(True) + + def test_fail(self): + sys.stderr.write('Write to stderr.') + sys.stdout.write('Write to stdout.') + self.assertTrue(False)