mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #32552 -- Added logger argument to DiscoverRunner.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							022d29c934
						
					
				
				
					commit
					b263f4b69d
				
			| @@ -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) | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user