mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Refs #32552 -- Added DiscoverRunner.log() to allow customization.
Thanks Carlton Gibson, Chris Jerdonek, and David Smith for reviews.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							cd19db10df
						
					
				
				
					commit
					a0410ffe8f
				
			| @@ -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))) | ||||
|                 self.log( | ||||
|                     'Including test tag(s): %s.' % ', '.join(sorted(self.tags)), | ||||
|                     level=logging.DEBUG, | ||||
|                 ) | ||||
|             if self.exclude_tags: | ||||
|                     print('Excluding test tag(s): %s.' % ', '.join(sorted(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))) | ||||
|             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): | ||||
|   | ||||
| @@ -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 | ||||
| ~~~~ | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
| ----------------- | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user