summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Jerdonek <chris.jerdonek@gmail.com>2021-08-09 13:18:51 -0400
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-08-24 09:23:01 +0200
commitb263f4b69db4093847ccc3b85e51cc7f3759e42c (patch)
tree1c20b6a8ae6fef70164340dd5ac8b37babcec537
parent022d29c934107c515dd6d3181945146a2077bdf0 (diff)
Fixed #32552 -- Added logger argument to DiscoverRunner.
-rw-r--r--django/test/runner.py26
-rw-r--r--docs/releases/4.0.txt7
-rw-r--r--docs/topics/testing/advanced.txt29
-rw-r--r--tests/test_runner/test_discover_runner.py21
4 files changed, 61 insertions, 22 deletions
diff --git a/django/test/runner.py b/django/test/runner.py
index eb5026b212..225bc19b09 100644
--- a/django/test/runner.py
+++ b/django/test/runner.py
@@ -561,7 +561,7 @@ class DiscoverRunner:
reverse=False, debug_mode=False, debug_sql=False, parallel=0,
tags=None, exclude_tags=None, test_name_patterns=None,
pdb=False, buffer=False, enable_faulthandler=True,
- timing=False, shuffle=False, **kwargs):
+ timing=False, shuffle=False, logger=None, **kwargs):
self.pattern = pattern
self.top_level = top_level
@@ -595,6 +595,7 @@ class DiscoverRunner:
}
self.shuffle = shuffle
self._shuffler = None
+ self.logger = logger
@classmethod
def add_arguments(cls, parser):
@@ -677,16 +678,23 @@ class DiscoverRunner:
def log(self, msg, level=None):
"""
- Log the given message at the given logging level.
+ Log the message at the given logging level (the default is INFO).
- A verbosity of 1 logs INFO (the default level) or above, and verbosity
- 2 or higher logs all levels.
+ If a logger isn't set, the message is instead printed to the console,
+ respecting the configured verbosity. A verbosity of 0 prints no output,
+ a verbosity of 1 prints INFO and above, and a verbosity of 2 or higher
+ prints all levels.
"""
- if self.verbosity <= 0 or (
- self.verbosity == 1 and level is not None and level < logging.INFO
- ):
- return
- print(msg)
+ if level is None:
+ level = logging.INFO
+ if self.logger is None:
+ if self.verbosity <= 0 or (
+ self.verbosity == 1 and level < logging.INFO
+ ):
+ return
+ print(msg)
+ else:
+ self.logger.log(level, msg)
def setup_test_environment(self, **kwargs):
setup_test_environment(debug=self.debug_mode)
diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt
index 24ce7285e0..aa45d1e1e9 100644
--- a/docs/releases/4.0.txt
+++ b/docs/releases/4.0.txt
@@ -356,8 +356,11 @@ 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.
+* The new ``logger`` argument to :class:`~django.test.runner.DiscoverRunner`
+ allows a Python :py:ref:`logger <logger>` to be used for logging.
+
+* The new :meth:`.DiscoverRunner.log` method provides a way to log messages
+ that uses the ``DiscoverRunner.logger``, or prints to the console if not set.
* Django test runner now supports a :option:`--shuffle <test --shuffle>` option
to execute tests in a random order.
diff --git a/docs/topics/testing/advanced.txt b/docs/topics/testing/advanced.txt
index 3265c5c641..c0251d8368 100644
--- a/docs/topics/testing/advanced.txt
+++ b/docs/topics/testing/advanced.txt
@@ -510,7 +510,7 @@ behavior. This class defines the ``run_tests()`` entry point, plus a
selection of other methods that are used by ``run_tests()`` to set up, execute
and tear down the test suite.
-.. class:: DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, 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, buffer=False, enable_faulthandler=True, timing=True, shuffle=False, **kwargs)
+.. class:: DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, 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, buffer=False, enable_faulthandler=True, timing=True, shuffle=False, logger=None, **kwargs)
``DiscoverRunner`` will search for tests in any file matching ``pattern``.
@@ -580,10 +580,15 @@ and tear down the test suite.
If ``shuffle`` is an integer, test cases will be shuffled in a random order
prior to execution, using the integer as a random seed. If ``shuffle`` is
``None``, the seed will be generated randomly. In both cases, the seed will
- be logged to the console and set to ``self.shuffle_seed`` prior to running
- tests. This option can be used to help detect tests that aren't properly
- isolated. :ref:`Grouping by test class <order-of-tests>` is preserved when
- using this option.
+ be logged and set to ``self.shuffle_seed`` prior to running tests. This
+ option can be used to help detect tests that aren't properly isolated.
+ :ref:`Grouping by test class <order-of-tests>` is preserved when using this
+ option.
+
+ ``logger`` can be used to pass a Python :py:ref:`Logger object <logger>`.
+ If provided, the logger will be used to log messages instead of printing to
+ the console. The logger object will respect its logging level rather than
+ the ``verbosity``.
Django may, from time to time, extend the capabilities of the test runner
by adding new arguments. The ``**kwargs`` declaration allows for this
@@ -601,7 +606,7 @@ and tear down the test suite.
.. versionadded:: 4.0
- The ``shuffle`` argument was added.
+ The ``logger`` and ``shuffle`` arguments were added.
Attributes
~~~~~~~~~~
@@ -726,11 +731,13 @@ Methods
.. 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.
+ If a ``logger`` is set, logs the message at the given integer
+ `logging level`_ (e.g. ``logging.DEBUG``, ``logging.INFO``, or
+ ``logging.WARNING``). Otherwise, the message is printed to the console,
+ respecting the current ``verbosity``. For example, no message will be
+ printed if the ``verbosity`` is 0, ``INFO`` and above will be printed if
+ the ``verbosity`` is at least 1, and ``DEBUG`` will be printed if it is at
+ least 2. The ``level`` defaults to ``logging.INFO``.
.. _`logging level`: https://docs.python.org/3/library/logging.html#levels
diff --git a/tests/test_runner/test_discover_runner.py b/tests/test_runner/test_discover_runner.py
index 625de94067..0012be5a7e 100644
--- a/tests/test_runner/test_discover_runner.py
+++ b/tests/test_runner/test_discover_runner.py
@@ -623,6 +623,27 @@ class DiscoverRunnerTests(SimpleTestCase):
runner.log(msg, level)
self.assertEqual(stdout.getvalue(), f'{msg}\n' if output else '')
+ def test_log_logger(self):
+ logger = logging.getLogger('test.logging')
+ cases = [
+ (None, 'INFO:test.logging:log message'),
+ # Test a low custom logging level.
+ (5, 'Level 5:test.logging:log message'),
+ (logging.DEBUG, 'DEBUG:test.logging:log message'),
+ (logging.INFO, 'INFO:test.logging:log message'),
+ (logging.WARNING, 'WARNING:test.logging:log message'),
+ # Test a high custom logging level.
+ (45, 'Level 45:test.logging:log message'),
+ ]
+ for level, expected in cases:
+ with self.subTest(level=level):
+ runner = DiscoverRunner(logger=logger)
+ # Pass a logging level smaller than the smallest level in cases
+ # in order to capture all messages.
+ with self.assertLogs('test.logging', level=1) as cm:
+ runner.log('log message', level)
+ self.assertEqual(cm.output, [expected])
+
class DiscoverRunnerGetDatabasesTests(SimpleTestCase):
runner = DiscoverRunner(verbosity=2)