mirror of
				https://github.com/django/django.git
				synced 2025-10-26 07:06:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			376 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			376 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import multiprocessing
 | |
| import sys
 | |
| from io import StringIO
 | |
| from unittest import skipIf
 | |
| 
 | |
| from django.apps import apps
 | |
| from django.core import checks
 | |
| from django.core.checks import Error, Warning
 | |
| from django.core.checks.messages import CheckMessage
 | |
| from django.core.checks.registry import CheckRegistry
 | |
| from django.core.management import call_command
 | |
| from django.core.management.base import CommandError
 | |
| from django.db import models
 | |
| from django.test import SimpleTestCase
 | |
| from django.test.utils import isolate_apps, override_settings, override_system_checks
 | |
| 
 | |
| from .models import SimpleModel, my_check
 | |
| 
 | |
| 
 | |
| class DummyObj:
 | |
|     def __repr__(self):
 | |
|         return "obj"
 | |
| 
 | |
| 
 | |
| class SystemCheckFrameworkTests(SimpleTestCase):
 | |
|     def test_register_and_run_checks(self):
 | |
|         def f(**kwargs):
 | |
|             calls[0] += 1
 | |
|             return [1, 2, 3]
 | |
| 
 | |
|         def f2(**kwargs):
 | |
|             return [4]
 | |
| 
 | |
|         def f3(**kwargs):
 | |
|             return [5]
 | |
| 
 | |
|         calls = [0]
 | |
| 
 | |
|         # test register as decorator
 | |
|         registry = CheckRegistry()
 | |
|         registry.register()(f)
 | |
|         registry.register("tag1", "tag2")(f2)
 | |
|         registry.register("tag2", deploy=True)(f3)
 | |
| 
 | |
|         # test register as function
 | |
|         registry2 = CheckRegistry()
 | |
|         registry2.register(f)
 | |
|         registry2.register(f2, "tag1", "tag2")
 | |
|         registry2.register(f3, "tag2", deploy=True)
 | |
| 
 | |
|         # check results
 | |
|         errors = registry.run_checks()
 | |
|         errors2 = registry2.run_checks()
 | |
|         self.assertEqual(errors, errors2)
 | |
|         self.assertEqual(sorted(errors), [1, 2, 3, 4])
 | |
|         self.assertEqual(calls[0], 2)
 | |
| 
 | |
|         errors = registry.run_checks(tags=["tag1"])
 | |
|         errors2 = registry2.run_checks(tags=["tag1"])
 | |
|         self.assertEqual(errors, errors2)
 | |
|         self.assertEqual(sorted(errors), [4])
 | |
| 
 | |
|         errors = registry.run_checks(
 | |
|             tags=["tag1", "tag2"], include_deployment_checks=True
 | |
|         )
 | |
|         errors2 = registry2.run_checks(
 | |
|             tags=["tag1", "tag2"], include_deployment_checks=True
 | |
|         )
 | |
|         self.assertEqual(errors, errors2)
 | |
|         self.assertEqual(sorted(errors), [4, 5])
 | |
| 
 | |
|     def test_register_no_kwargs_error(self):
 | |
|         registry = CheckRegistry()
 | |
|         msg = "Check functions must accept keyword arguments (**kwargs)."
 | |
|         with self.assertRaisesMessage(TypeError, msg):
 | |
| 
 | |
|             @registry.register
 | |
|             def no_kwargs(app_configs, databases):
 | |
|                 pass
 | |
| 
 | |
|     def test_register_run_checks_non_iterable(self):
 | |
|         registry = CheckRegistry()
 | |
| 
 | |
|         @registry.register
 | |
|         def return_non_iterable(**kwargs):
 | |
|             return Error("Message")
 | |
| 
 | |
|         msg = (
 | |
|             "The function %r did not return a list. All functions registered "
 | |
|             "with the checks registry must return a list." % return_non_iterable
 | |
|         )
 | |
|         with self.assertRaisesMessage(TypeError, msg):
 | |
|             registry.run_checks()
 | |
| 
 | |
| 
 | |
| class MessageTests(SimpleTestCase):
 | |
|     def test_printing(self):
 | |
|         e = Error("Message", hint="Hint", obj=DummyObj())
 | |
|         expected = "obj: Message\n\tHINT: Hint"
 | |
|         self.assertEqual(str(e), expected)
 | |
| 
 | |
|     def test_printing_no_hint(self):
 | |
|         e = Error("Message", obj=DummyObj())
 | |
|         expected = "obj: Message"
 | |
|         self.assertEqual(str(e), expected)
 | |
| 
 | |
|     def test_printing_no_object(self):
 | |
|         e = Error("Message", hint="Hint")
 | |
|         expected = "?: Message\n\tHINT: Hint"
 | |
|         self.assertEqual(str(e), expected)
 | |
| 
 | |
|     def test_printing_with_given_id(self):
 | |
|         e = Error("Message", hint="Hint", obj=DummyObj(), id="ID")
 | |
|         expected = "obj: (ID) Message\n\tHINT: Hint"
 | |
|         self.assertEqual(str(e), expected)
 | |
| 
 | |
|     def test_printing_field_error(self):
 | |
|         field = SimpleModel._meta.get_field("field")
 | |
|         e = Error("Error", obj=field)
 | |
|         expected = "check_framework.SimpleModel.field: Error"
 | |
|         self.assertEqual(str(e), expected)
 | |
| 
 | |
|     def test_printing_model_error(self):
 | |
|         e = Error("Error", obj=SimpleModel)
 | |
|         expected = "check_framework.SimpleModel: Error"
 | |
|         self.assertEqual(str(e), expected)
 | |
| 
 | |
|     def test_printing_manager_error(self):
 | |
|         manager = SimpleModel.manager
 | |
|         e = Error("Error", obj=manager)
 | |
|         expected = "check_framework.SimpleModel.manager: Error"
 | |
|         self.assertEqual(str(e), expected)
 | |
| 
 | |
|     def test_equal_to_self(self):
 | |
|         e = Error("Error", obj=SimpleModel)
 | |
|         self.assertEqual(e, e)
 | |
| 
 | |
|     def test_equal_to_same_constructed_check(self):
 | |
|         e1 = Error("Error", obj=SimpleModel)
 | |
|         e2 = Error("Error", obj=SimpleModel)
 | |
|         self.assertEqual(e1, e2)
 | |
| 
 | |
|     def test_not_equal_to_different_constructed_check(self):
 | |
|         e1 = Error("Error", obj=SimpleModel)
 | |
|         e2 = Error("Error2", obj=SimpleModel)
 | |
|         self.assertNotEqual(e1, e2)
 | |
| 
 | |
|     def test_not_equal_to_non_check(self):
 | |
|         e = Error("Error", obj=DummyObj())
 | |
|         self.assertNotEqual(e, "a string")
 | |
| 
 | |
|     def test_invalid_level(self):
 | |
|         msg = "The first argument should be level."
 | |
|         with self.assertRaisesMessage(TypeError, msg):
 | |
|             CheckMessage("ERROR", "Message")
 | |
| 
 | |
| 
 | |
| def simple_system_check(**kwargs):
 | |
|     simple_system_check.kwargs = kwargs
 | |
|     return []
 | |
| 
 | |
| 
 | |
| def tagged_system_check(**kwargs):
 | |
|     tagged_system_check.kwargs = kwargs
 | |
|     return [checks.Warning("System Check")]
 | |
| 
 | |
| 
 | |
| tagged_system_check.tags = ["simpletag"]
 | |
| 
 | |
| 
 | |
| def deployment_system_check(**kwargs):
 | |
|     deployment_system_check.kwargs = kwargs
 | |
|     return [checks.Warning("Deployment Check")]
 | |
| 
 | |
| 
 | |
| deployment_system_check.tags = ["deploymenttag"]
 | |
| 
 | |
| 
 | |
| class CheckCommandTests(SimpleTestCase):
 | |
|     def setUp(self):
 | |
|         simple_system_check.kwargs = None
 | |
|         tagged_system_check.kwargs = None
 | |
|         self.old_stdout, self.old_stderr = sys.stdout, sys.stderr
 | |
|         sys.stdout, sys.stderr = StringIO(), StringIO()
 | |
| 
 | |
|     def tearDown(self):
 | |
|         sys.stdout, sys.stderr = self.old_stdout, self.old_stderr
 | |
| 
 | |
|     @override_system_checks([simple_system_check, tagged_system_check])
 | |
|     def test_simple_call(self):
 | |
|         call_command("check")
 | |
|         self.assertEqual(
 | |
|             simple_system_check.kwargs, {"app_configs": None, "databases": None}
 | |
|         )
 | |
|         self.assertEqual(
 | |
|             tagged_system_check.kwargs, {"app_configs": None, "databases": None}
 | |
|         )
 | |
| 
 | |
|     @override_system_checks([simple_system_check, tagged_system_check])
 | |
|     def test_given_app(self):
 | |
|         call_command("check", "auth", "admin")
 | |
|         auth_config = apps.get_app_config("auth")
 | |
|         admin_config = apps.get_app_config("admin")
 | |
|         self.assertEqual(
 | |
|             simple_system_check.kwargs,
 | |
|             {"app_configs": [auth_config, admin_config], "databases": None},
 | |
|         )
 | |
|         self.assertEqual(
 | |
|             tagged_system_check.kwargs,
 | |
|             {"app_configs": [auth_config, admin_config], "databases": None},
 | |
|         )
 | |
| 
 | |
|     @override_system_checks([simple_system_check, tagged_system_check])
 | |
|     def test_given_tag(self):
 | |
|         call_command("check", tags=["simpletag"])
 | |
|         self.assertIsNone(simple_system_check.kwargs)
 | |
|         self.assertEqual(
 | |
|             tagged_system_check.kwargs, {"app_configs": None, "databases": None}
 | |
|         )
 | |
| 
 | |
|     @override_system_checks([simple_system_check, tagged_system_check])
 | |
|     def test_invalid_tag(self):
 | |
|         msg = 'There is no system check with the "missingtag" tag.'
 | |
|         with self.assertRaisesMessage(CommandError, msg):
 | |
|             call_command("check", tags=["missingtag"])
 | |
| 
 | |
|     @override_system_checks([simple_system_check])
 | |
|     def test_list_tags_empty(self):
 | |
|         call_command("check", list_tags=True)
 | |
|         self.assertEqual("\n", sys.stdout.getvalue())
 | |
| 
 | |
|     @override_system_checks([tagged_system_check])
 | |
|     def test_list_tags(self):
 | |
|         call_command("check", list_tags=True)
 | |
|         self.assertEqual("simpletag\n", sys.stdout.getvalue())
 | |
| 
 | |
|     @override_system_checks(
 | |
|         [tagged_system_check], deployment_checks=[deployment_system_check]
 | |
|     )
 | |
|     def test_list_deployment_check_omitted(self):
 | |
|         call_command("check", list_tags=True)
 | |
|         self.assertEqual("simpletag\n", sys.stdout.getvalue())
 | |
| 
 | |
|     @override_system_checks(
 | |
|         [tagged_system_check], deployment_checks=[deployment_system_check]
 | |
|     )
 | |
|     def test_list_deployment_check_included(self):
 | |
|         call_command("check", deploy=True, list_tags=True)
 | |
|         self.assertEqual("deploymenttag\nsimpletag\n", sys.stdout.getvalue())
 | |
| 
 | |
|     @override_system_checks(
 | |
|         [tagged_system_check], deployment_checks=[deployment_system_check]
 | |
|     )
 | |
|     def test_tags_deployment_check_omitted(self):
 | |
|         msg = 'There is no system check with the "deploymenttag" tag.'
 | |
|         with self.assertRaisesMessage(CommandError, msg):
 | |
|             call_command("check", tags=["deploymenttag"])
 | |
| 
 | |
|     @override_system_checks(
 | |
|         [tagged_system_check], deployment_checks=[deployment_system_check]
 | |
|     )
 | |
|     def test_tags_deployment_check_included(self):
 | |
|         call_command("check", deploy=True, tags=["deploymenttag"])
 | |
|         self.assertIn("Deployment Check", sys.stderr.getvalue())
 | |
| 
 | |
|     @override_system_checks([tagged_system_check])
 | |
|     def test_fail_level(self):
 | |
|         with self.assertRaises(CommandError):
 | |
|             call_command("check", fail_level="WARNING")
 | |
| 
 | |
| 
 | |
| def custom_error_system_check(app_configs, **kwargs):
 | |
|     return [Error("Error", id="myerrorcheck.E001")]
 | |
| 
 | |
| 
 | |
| def custom_warning_system_check(app_configs, **kwargs):
 | |
|     return [Warning("Warning", id="mywarningcheck.E001")]
 | |
| 
 | |
| 
 | |
| class SilencingCheckTests(SimpleTestCase):
 | |
|     def setUp(self):
 | |
|         self.old_stdout, self.old_stderr = sys.stdout, sys.stderr
 | |
|         self.stdout, self.stderr = StringIO(), StringIO()
 | |
|         sys.stdout, sys.stderr = self.stdout, self.stderr
 | |
| 
 | |
|     def tearDown(self):
 | |
|         sys.stdout, sys.stderr = self.old_stdout, self.old_stderr
 | |
| 
 | |
|     @override_settings(SILENCED_SYSTEM_CHECKS=["myerrorcheck.E001"])
 | |
|     @override_system_checks([custom_error_system_check])
 | |
|     def test_silenced_error(self):
 | |
|         out = StringIO()
 | |
|         err = StringIO()
 | |
|         call_command("check", stdout=out, stderr=err)
 | |
|         self.assertEqual(
 | |
|             out.getvalue(), "System check identified no issues (1 silenced).\n"
 | |
|         )
 | |
|         self.assertEqual(err.getvalue(), "")
 | |
| 
 | |
|     @override_settings(SILENCED_SYSTEM_CHECKS=["mywarningcheck.E001"])
 | |
|     @override_system_checks([custom_warning_system_check])
 | |
|     def test_silenced_warning(self):
 | |
|         out = StringIO()
 | |
|         err = StringIO()
 | |
|         call_command("check", stdout=out, stderr=err)
 | |
|         self.assertEqual(
 | |
|             out.getvalue(), "System check identified no issues (1 silenced).\n"
 | |
|         )
 | |
|         self.assertEqual(err.getvalue(), "")
 | |
| 
 | |
| 
 | |
| class CheckFrameworkReservedNamesTests(SimpleTestCase):
 | |
|     @isolate_apps("check_framework", kwarg_name="apps")
 | |
|     @override_system_checks([checks.model_checks.check_all_models])
 | |
|     def test_model_check_method_not_shadowed(self, apps):
 | |
|         class ModelWithAttributeCalledCheck(models.Model):
 | |
|             check = 42
 | |
| 
 | |
|         class ModelWithFieldCalledCheck(models.Model):
 | |
|             check = models.IntegerField()
 | |
| 
 | |
|         class ModelWithRelatedManagerCalledCheck(models.Model):
 | |
|             pass
 | |
| 
 | |
|         class ModelWithDescriptorCalledCheck(models.Model):
 | |
|             check = models.ForeignKey(
 | |
|                 ModelWithRelatedManagerCalledCheck, models.CASCADE
 | |
|             )
 | |
|             article = models.ForeignKey(
 | |
|                 ModelWithRelatedManagerCalledCheck,
 | |
|                 models.CASCADE,
 | |
|                 related_name="check",
 | |
|             )
 | |
| 
 | |
|         errors = checks.run_checks(app_configs=apps.get_app_configs())
 | |
|         expected = [
 | |
|             Error(
 | |
|                 "The 'ModelWithAttributeCalledCheck.check()' class method is "
 | |
|                 "currently overridden by 42.",
 | |
|                 obj=ModelWithAttributeCalledCheck,
 | |
|                 id="models.E020",
 | |
|             ),
 | |
|             Error(
 | |
|                 "The 'ModelWithFieldCalledCheck.check()' class method is "
 | |
|                 "currently overridden by %r." % ModelWithFieldCalledCheck.check,
 | |
|                 obj=ModelWithFieldCalledCheck,
 | |
|                 id="models.E020",
 | |
|             ),
 | |
|             Error(
 | |
|                 "The 'ModelWithRelatedManagerCalledCheck.check()' class method is "
 | |
|                 "currently overridden by %r."
 | |
|                 % ModelWithRelatedManagerCalledCheck.check,
 | |
|                 obj=ModelWithRelatedManagerCalledCheck,
 | |
|                 id="models.E020",
 | |
|             ),
 | |
|             Error(
 | |
|                 "The 'ModelWithDescriptorCalledCheck.check()' class method is "
 | |
|                 "currently overridden by %r." % ModelWithDescriptorCalledCheck.check,
 | |
|                 obj=ModelWithDescriptorCalledCheck,
 | |
|                 id="models.E020",
 | |
|             ),
 | |
|         ]
 | |
|         self.assertEqual(errors, expected)
 | |
| 
 | |
| 
 | |
| @skipIf(
 | |
|     multiprocessing.get_start_method() == "spawn",
 | |
|     "Spawning reimports modules, overwriting my_check.did_run to False, making this "
 | |
|     "test useless.",
 | |
| )
 | |
| class ChecksRunDuringTests(SimpleTestCase):
 | |
|     databases = "__all__"
 | |
| 
 | |
|     def test_registered_check_did_run(self):
 | |
|         self.assertTrue(my_check.did_run)
 |