mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	Refs #21429 -- Added SimpleTestCase.assertNoLogs() on Python < 3.10.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							d3ecef26b9
						
					
				
				
					commit
					7ca7f4495b
				
			| @@ -1,6 +1,7 @@ | |||||||
| import asyncio | import asyncio | ||||||
| import difflib | import difflib | ||||||
| import json | import json | ||||||
|  | import logging | ||||||
| import posixpath | import posixpath | ||||||
| import sys | import sys | ||||||
| import threading | import threading | ||||||
| @@ -43,6 +44,7 @@ from django.test.utils import ( | |||||||
| ) | ) | ||||||
| from django.utils.deprecation import RemovedInDjango41Warning | from django.utils.deprecation import RemovedInDjango41Warning | ||||||
| from django.utils.functional import classproperty | from django.utils.functional import classproperty | ||||||
|  | from django.utils.version import PY310 | ||||||
| from django.views.static import serve | from django.views.static import serve | ||||||
|  |  | ||||||
| __all__ = ('TestCase', 'TransactionTestCase', | __all__ = ('TestCase', 'TransactionTestCase', | ||||||
| @@ -730,6 +732,29 @@ class SimpleTestCase(unittest.TestCase): | |||||||
|             *args, **kwargs |             *args, **kwargs | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |     # A similar method is available in Python 3.10+. | ||||||
|  |     if not PY310: | ||||||
|  |         @contextmanager | ||||||
|  |         def assertNoLogs(self, logger, level=None): | ||||||
|  |             """ | ||||||
|  |             Assert no messages are logged on the logger, with at least the | ||||||
|  |             given level. | ||||||
|  |             """ | ||||||
|  |             if isinstance(level, int): | ||||||
|  |                 level = logging.getLevelName(level) | ||||||
|  |             elif level is None: | ||||||
|  |                 level = 'INFO' | ||||||
|  |             try: | ||||||
|  |                 with self.assertLogs(logger, level) as cm: | ||||||
|  |                     yield | ||||||
|  |             except AssertionError as e: | ||||||
|  |                 msg = e.args[0] | ||||||
|  |                 expected_msg = f'no logs of level {level} or higher triggered on {logger}' | ||||||
|  |                 if msg != expected_msg: | ||||||
|  |                     raise e | ||||||
|  |             else: | ||||||
|  |                 self.fail(f'Unexpected logs found: {cm.output!r}') | ||||||
|  |  | ||||||
|     def assertFieldOutput(self, fieldclass, valid, invalid, field_args=None, |     def assertFieldOutput(self, fieldclass, valid, invalid, field_args=None, | ||||||
|                           field_kwargs=None, empty_value=''): |                           field_kwargs=None, empty_value=''): | ||||||
|         """ |         """ | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ PY36 = sys.version_info >= (3, 6) | |||||||
| PY37 = sys.version_info >= (3, 7) | PY37 = sys.version_info >= (3, 7) | ||||||
| PY38 = sys.version_info >= (3, 8) | PY38 = sys.version_info >= (3, 8) | ||||||
| PY39 = sys.version_info >= (3, 9) | PY39 = sys.version_info >= (3, 9) | ||||||
|  | PY310 = sys.version_info >= (3, 10) | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_version(version=None): | def get_version(version=None): | ||||||
|   | |||||||
| @@ -82,9 +82,8 @@ class AdminSidebarTests(TestCase): | |||||||
|     def test_included_app_list_template_context_fully_set(self): |     def test_included_app_list_template_context_fully_set(self): | ||||||
|         # All context variables should be set when rendering the sidebar. |         # All context variables should be set when rendering the sidebar. | ||||||
|         url = reverse('test_with_sidebar:auth_user_changelist') |         url = reverse('test_with_sidebar:auth_user_changelist') | ||||||
|         with self.assertRaisesMessage(AssertionError, 'no logs'): |         with self.assertNoLogs('django.template', 'DEBUG'): | ||||||
|             with self.assertLogs('django.template', 'DEBUG'): |             self.client.get(url) | ||||||
|                 self.client.get(url) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @override_settings(ROOT_URLCONF='admin_views.test_nav_sidebar') | @override_settings(ROOT_URLCONF='admin_views.test_nav_sidebar') | ||||||
|   | |||||||
| @@ -454,10 +454,9 @@ class CsrfViewMiddlewareTestMixin: | |||||||
|         """ |         """ | ||||||
|         ensure_csrf_cookie() doesn't log warnings (#19436). |         ensure_csrf_cookie() doesn't log warnings (#19436). | ||||||
|         """ |         """ | ||||||
|         with self.assertRaisesMessage(AssertionError, 'no logs'): |         with self.assertNoLogs('django.request', 'WARNING'): | ||||||
|             with self.assertLogs('django.request', 'WARNING'): |             req = self._get_GET_no_csrf_cookie_request() | ||||||
|                 req = self._get_GET_no_csrf_cookie_request() |             ensure_csrf_cookie_view(req) | ||||||
|                 ensure_csrf_cookie_view(req) |  | ||||||
|  |  | ||||||
|     def test_post_data_read_failure(self): |     def test_post_data_read_failure(self): | ||||||
|         """ |         """ | ||||||
|   | |||||||
| @@ -72,9 +72,8 @@ class GeoAdminTest(SimpleTestCase): | |||||||
|     def test_olwidget_empty_string(self): |     def test_olwidget_empty_string(self): | ||||||
|         geoadmin = site._registry[City] |         geoadmin = site._registry[City] | ||||||
|         form = geoadmin.get_changelist_form(None)({'point': ''}) |         form = geoadmin.get_changelist_form(None)({'point': ''}) | ||||||
|         with self.assertRaisesMessage(AssertionError, 'no logs'): |         with self.assertNoLogs('django.contrib.gis', 'ERROR'): | ||||||
|             with self.assertLogs('django.contrib.gis', 'ERROR'): |             output = str(form['point']) | ||||||
|                 output = str(form['point']) |  | ||||||
|         self.assertInHTML( |         self.assertInHTML( | ||||||
|             '<textarea id="id_point" class="vWKTField required" cols="150"' |             '<textarea id="id_point" class="vWKTField required" cols="150"' | ||||||
|             ' rows="10" name="point"></textarea>', |             ' rows="10" name="point"></textarea>', | ||||||
|   | |||||||
| @@ -427,9 +427,8 @@ class GeoLookupTest(TestCase): | |||||||
|  |  | ||||||
|     def test_wkt_string_in_lookup(self): |     def test_wkt_string_in_lookup(self): | ||||||
|         # Valid WKT strings don't emit error logs. |         # Valid WKT strings don't emit error logs. | ||||||
|         with self.assertRaisesMessage(AssertionError, 'no logs'): |         with self.assertNoLogs('django.contrib.gis', 'ERROR'): | ||||||
|             with self.assertLogs('django.contrib.gis', 'ERROR'): |             State.objects.filter(poly__intersects='LINESTRING(0 0, 1 1, 5 5)') | ||||||
|                 State.objects.filter(poly__intersects='LINESTRING(0 0, 1 1, 5 5)') |  | ||||||
|  |  | ||||||
|     @skipUnlessDBFeature("supports_relate_lookup") |     @skipUnlessDBFeature("supports_relate_lookup") | ||||||
|     def test_relate_lookup(self): |     def test_relate_lookup(self): | ||||||
|   | |||||||
| @@ -177,9 +177,8 @@ class MiddlewareNotUsedTests(SimpleTestCase): | |||||||
|         MIDDLEWARE=['middleware_exceptions.tests.MyMiddleware'], |         MIDDLEWARE=['middleware_exceptions.tests.MyMiddleware'], | ||||||
|     ) |     ) | ||||||
|     def test_do_not_log_when_debug_is_false(self): |     def test_do_not_log_when_debug_is_false(self): | ||||||
|         with self.assertRaisesMessage(AssertionError, 'no logs'): |         with self.assertNoLogs('django.request', 'DEBUG'): | ||||||
|             with self.assertLogs('django.request', 'DEBUG'): |             self.client.get('/middleware_exceptions/view/') | ||||||
|                 self.client.get('/middleware_exceptions/view/') |  | ||||||
|  |  | ||||||
|     @override_settings(MIDDLEWARE=[ |     @override_settings(MIDDLEWARE=[ | ||||||
|         'middleware_exceptions.middleware.SyncAndAsyncMiddleware', |         'middleware_exceptions.middleware.SyncAndAsyncMiddleware', | ||||||
|   | |||||||
| @@ -62,6 +62,5 @@ class VariableResolveLoggingTests(SimpleTestCase): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_no_log_when_variable_exists(self): |     def test_no_log_when_variable_exists(self): | ||||||
|         with self.assertRaisesMessage(AssertionError, 'no logs'): |         with self.assertNoLogs('django.template', self.loglevel): | ||||||
|             with self.assertLogs('django.template', self.loglevel): |             Variable('article.section').resolve({'article': {'section': 'News'}}) | ||||||
|                 Variable('article.section').resolve({'article': {'section': 'News'}}) |  | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import logging | ||||||
| import os | import os | ||||||
| import unittest | import unittest | ||||||
| import warnings | import warnings | ||||||
| @@ -26,6 +27,7 @@ from django.test.utils import ( | |||||||
| ) | ) | ||||||
| from django.urls import NoReverseMatch, path, reverse, reverse_lazy | from django.urls import NoReverseMatch, path, reverse, reverse_lazy | ||||||
| from django.utils.deprecation import RemovedInDjango41Warning | from django.utils.deprecation import RemovedInDjango41Warning | ||||||
|  | from django.utils.log import DEFAULT_LOGGING | ||||||
|  |  | ||||||
| from .models import Car, Person, PossessedCar | from .models import Car, Person, PossessedCar | ||||||
| from .views import empty_response | from .views import empty_response | ||||||
| @@ -1105,6 +1107,47 @@ class AssertWarnsMessageTests(SimpleTestCase): | |||||||
|             func1() |             func1() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # TODO: Remove when dropping support for PY39. | ||||||
|  | class AssertNoLogsTest(SimpleTestCase): | ||||||
|  |     @classmethod | ||||||
|  |     def setUpClass(cls): | ||||||
|  |         super().setUpClass() | ||||||
|  |         logging.config.dictConfig(DEFAULT_LOGGING) | ||||||
|  |         cls.addClassCleanup(logging.config.dictConfig, settings.LOGGING) | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         self.logger = logging.getLogger('django') | ||||||
|  |  | ||||||
|  |     @override_settings(DEBUG=True) | ||||||
|  |     def test_fails_when_log_emitted(self): | ||||||
|  |         msg = "Unexpected logs found: ['INFO:django:FAIL!']" | ||||||
|  |         with self.assertRaisesMessage(AssertionError, msg): | ||||||
|  |             with self.assertNoLogs('django', 'INFO'): | ||||||
|  |                 self.logger.info('FAIL!') | ||||||
|  |  | ||||||
|  |     @override_settings(DEBUG=True) | ||||||
|  |     def test_text_level(self): | ||||||
|  |         with self.assertNoLogs('django', 'INFO'): | ||||||
|  |             self.logger.debug('DEBUG logs are ignored.') | ||||||
|  |  | ||||||
|  |     @override_settings(DEBUG=True) | ||||||
|  |     def test_int_level(self): | ||||||
|  |         with self.assertNoLogs('django', logging.INFO): | ||||||
|  |             self.logger.debug('DEBUG logs are ignored.') | ||||||
|  |  | ||||||
|  |     @override_settings(DEBUG=True) | ||||||
|  |     def test_default_level(self): | ||||||
|  |         with self.assertNoLogs('django'): | ||||||
|  |             self.logger.debug('DEBUG logs are ignored.') | ||||||
|  |  | ||||||
|  |     @override_settings(DEBUG=True) | ||||||
|  |     def test_does_not_hide_other_failures(self): | ||||||
|  |         msg = '1 != 2' | ||||||
|  |         with self.assertRaisesMessage(AssertionError, msg): | ||||||
|  |             with self.assertNoLogs('django'): | ||||||
|  |                 self.assertEqual(1, 2) | ||||||
|  |  | ||||||
|  |  | ||||||
| class AssertFieldOutputTests(SimpleTestCase): | class AssertFieldOutputTests(SimpleTestCase): | ||||||
|  |  | ||||||
|     def test_assert_field_output(self): |     def test_assert_field_output(self): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user