Refs #32552 -- Added DiscoverRunner.log() to allow customization.

Thanks Carlton Gibson, Chris Jerdonek, and David Smith for reviews.
This commit is contained in:
Daniyal 2021-03-19 14:50:08 +05:30 committed by Mariusz Felisiak
parent cd19db10df
commit a0410ffe8f
4 changed files with 82 additions and 11 deletions

View File

@ -581,6 +581,19 @@ class DiscoverRunner:
),
)
def log(self, msg, level=None):
"""
Log the given message at the given logging level.
A verbosity of 1 logs INFO (the default level) or above, and verbosity
2 or higher logs all levels.
"""
if self.verbosity <= 0 or (
self.verbosity == 1 and level is not None and level < logging.INFO
):
return
print(msg)
def setup_test_environment(self, **kwargs):
setup_test_environment(debug=self.debug_mode)
unittest.installHandler()
@ -639,11 +652,16 @@ class DiscoverRunner:
all_tests.extend(iter_test_cases(extra_tests))
if self.tags or self.exclude_tags:
if self.verbosity >= 2:
if self.tags:
print('Including test tag(s): %s.' % ', '.join(sorted(self.tags)))
if self.exclude_tags:
print('Excluding test tag(s): %s.' % ', '.join(sorted(self.exclude_tags)))
if self.tags:
self.log(
'Including test tag(s): %s.' % ', '.join(sorted(self.tags)),
level=logging.DEBUG,
)
if self.exclude_tags:
self.log(
'Excluding test tag(s): %s.' % ', '.join(sorted(self.exclude_tags)),
level=logging.DEBUG,
)
all_tests = filter_tests_by_tags(all_tests, self.tags, self.exclude_tags)
# Put the failures detected at load time first for quicker feedback.
@ -651,8 +669,7 @@ class DiscoverRunner:
# found or that couldn't be loaded due to syntax errors.
test_types = (unittest.loader._FailedTest, *self.reorder_by)
all_tests = list(reorder_tests(all_tests, test_types, self.reverse))
if self.verbosity >= 1:
print('Found %d tests.' % len(all_tests))
self.log('Found %d tests.' % len(all_tests), level=logging.INFO)
suite = self.test_suite(all_tests)
if self.parallel > 1:
@ -736,10 +753,12 @@ class DiscoverRunner:
def get_databases(self, suite):
databases = self._get_databases(suite)
if self.verbosity >= 2:
unused_databases = [alias for alias in connections if alias not in databases]
if unused_databases:
print('Skipping setup of unused database(s): %s.' % ', '.join(sorted(unused_databases)))
unused_databases = [alias for alias in connections if alias not in databases]
if unused_databases:
self.log(
'Skipping setup of unused database(s): %s.' % ', '.join(sorted(unused_databases)),
level=logging.DEBUG,
)
return databases
def run_tests(self, test_labels, extra_tests=None, **kwargs):

View File

@ -294,6 +294,9 @@ Tests
* Django test runner now supports a :option:`--buffer <test --buffer>` option
with parallel tests.
* The new :meth:`.DiscoverRunner.log` method allows customizing the way
messages are logged.
URLs
~~~~

View File

@ -705,6 +705,17 @@ Methods
Computes and returns a return code based on a test suite, and the result
from that test suite.
.. method:: DiscoverRunner.log(msg, level=None)
.. versionadded:: 4.0
Prints to the console a message with the given integer `logging level`_
(e.g. ``logging.DEBUG``, ``logging.INFO``, or ``logging.WARNING``),
respecting the current ``verbosity``. For example, an ``INFO`` message will
be logged if the ``verbosity`` is at least 1, and ``DEBUG`` will be logged
if it is at least 2.
.. _`logging level`: https://docs.python.org/3/library/logging.html#levels
Testing utilities
-----------------

View File

@ -1,3 +1,4 @@
import logging
import os
import unittest.loader
from argparse import ArgumentParser
@ -378,6 +379,43 @@ class DiscoverRunnerTests(SimpleTestCase):
self.assertTrue(isinstance(runner.time_keeper, TimeKeeper))
self.assertIn('test', stderr.getvalue())
def test_log(self):
custom_low_level = 5
custom_high_level = 45
msg = 'logging message'
cases = [
(0, None, False),
(0, custom_low_level, False),
(0, logging.DEBUG, False),
(0, logging.INFO, False),
(0, logging.WARNING, False),
(0, custom_high_level, False),
(1, None, True),
(1, custom_low_level, False),
(1, logging.DEBUG, False),
(1, logging.INFO, True),
(1, logging.WARNING, True),
(1, custom_high_level, True),
(2, None, True),
(2, custom_low_level, True),
(2, logging.DEBUG, True),
(2, logging.INFO, True),
(2, logging.WARNING, True),
(2, custom_high_level, True),
(3, None, True),
(3, custom_low_level, True),
(3, logging.DEBUG, True),
(3, logging.INFO, True),
(3, logging.WARNING, True),
(3, custom_high_level, True),
]
for verbosity, level, output in cases:
with self.subTest(verbosity=verbosity, level=level):
with captured_stdout() as stdout:
runner = DiscoverRunner(verbosity=verbosity)
runner.log(msg, level)
self.assertEqual(stdout.getvalue(), f'{msg}\n' if output else '')
class DiscoverRunnerGetDatabasesTests(SimpleTestCase):
runner = DiscoverRunner(verbosity=2)