mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +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): |     def setup_test_environment(self, **kwargs): | ||||||
|         setup_test_environment(debug=self.debug_mode) |         setup_test_environment(debug=self.debug_mode) | ||||||
|         unittest.installHandler() |         unittest.installHandler() | ||||||
| @@ -639,11 +652,16 @@ class DiscoverRunner: | |||||||
|         all_tests.extend(iter_test_cases(extra_tests)) |         all_tests.extend(iter_test_cases(extra_tests)) | ||||||
|  |  | ||||||
|         if self.tags or self.exclude_tags: |         if self.tags or self.exclude_tags: | ||||||
|             if self.verbosity >= 2: |  | ||||||
|             if self.tags: |             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: |             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) |             all_tests = filter_tests_by_tags(all_tests, self.tags, self.exclude_tags) | ||||||
|  |  | ||||||
|         # Put the failures detected at load time first for quicker feedback. |         # 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. |         # found or that couldn't be loaded due to syntax errors. | ||||||
|         test_types = (unittest.loader._FailedTest, *self.reorder_by) |         test_types = (unittest.loader._FailedTest, *self.reorder_by) | ||||||
|         all_tests = list(reorder_tests(all_tests, test_types, self.reverse)) |         all_tests = list(reorder_tests(all_tests, test_types, self.reverse)) | ||||||
|         if self.verbosity >= 1: |         self.log('Found %d tests.' % len(all_tests), level=logging.INFO) | ||||||
|             print('Found %d tests.' % len(all_tests)) |  | ||||||
|         suite = self.test_suite(all_tests) |         suite = self.test_suite(all_tests) | ||||||
|  |  | ||||||
|         if self.parallel > 1: |         if self.parallel > 1: | ||||||
| @@ -736,10 +753,12 @@ class DiscoverRunner: | |||||||
|  |  | ||||||
|     def get_databases(self, suite): |     def get_databases(self, suite): | ||||||
|         databases = self._get_databases(suite) |         databases = self._get_databases(suite) | ||||||
|         if self.verbosity >= 2: |  | ||||||
|         unused_databases = [alias for alias in connections if alias not in databases] |         unused_databases = [alias for alias in connections if alias not in databases] | ||||||
|         if unused_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 |         return databases | ||||||
|  |  | ||||||
|     def run_tests(self, test_labels, extra_tests=None, **kwargs): |     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 | * Django test runner now supports a :option:`--buffer <test --buffer>` option | ||||||
|   with parallel tests. |   with parallel tests. | ||||||
|  |  | ||||||
|  | * The new :meth:`.DiscoverRunner.log` method allows customizing the way | ||||||
|  |   messages are logged. | ||||||
|  |  | ||||||
| URLs | URLs | ||||||
| ~~~~ | ~~~~ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -705,6 +705,17 @@ Methods | |||||||
|     Computes and returns a return code based on a test suite, and the result |     Computes and returns a return code based on a test suite, and the result | ||||||
|     from that test suite. |     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 | Testing utilities | ||||||
| ----------------- | ----------------- | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import logging | ||||||
| import os | import os | ||||||
| import unittest.loader | import unittest.loader | ||||||
| from argparse import ArgumentParser | from argparse import ArgumentParser | ||||||
| @@ -378,6 +379,43 @@ class DiscoverRunnerTests(SimpleTestCase): | |||||||
|         self.assertTrue(isinstance(runner.time_keeper, TimeKeeper)) |         self.assertTrue(isinstance(runner.time_keeper, TimeKeeper)) | ||||||
|         self.assertIn('test', stderr.getvalue()) |         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): | class DiscoverRunnerGetDatabasesTests(SimpleTestCase): | ||||||
|     runner = DiscoverRunner(verbosity=2) |     runner = DiscoverRunner(verbosity=2) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user