def test_cache_compatibility(self): compatible_cache = { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', } incompatible_cache = { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'cache_table' } with self.settings(CACHES={'default': compatible_cache, 'secondary': incompatible_cache}): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, []) warning001 = Warning( 'Cache backend %r is not supported by django-cachalot.' % 'django.core.cache.backends.db.DatabaseCache', hint='Switch to a supported cache backend ' 'like Redis or Memcached.', id='cachalot.W001') with self.settings(CACHES={'default': incompatible_cache}): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, [warning001]) with self.settings(CACHES={'default': compatible_cache, 'secondary': incompatible_cache}, CACHALOT_CACHE='secondary'): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, [warning001])
def test_generic_foreign_key_checks_are_performed(self): class Model(models.Model): content_object = GenericForeignKey() with mock.patch.object(GenericForeignKey, 'check') as check: checks.run_checks(app_configs=self.apps.get_app_configs()) check.assert_called_once_with()
def test_username_non_unique(self): """ A non-unique USERNAME_FIELD should raise an error only if we use the default authentication backend. Otherwise, an warning should be raised. """ errors = checks.run_checks() expected = [ checks.Error( "'CustomUserNonUniqueUsername.username' must be " "unique because it is named as the 'USERNAME_FIELD'.", obj=CustomUserNonUniqueUsername, id='auth.E003', ), ] self.assertEqual(errors, expected) with self.settings(AUTHENTICATION_BACKENDS=['my.custom.backend']): errors = checks.run_checks() expected = [ checks.Warning( "'CustomUserNonUniqueUsername.username' is named as " "the 'USERNAME_FIELD', but it is not unique.", hint='Ensure that your authentication backend(s) can handle non-unique usernames.', obj=CustomUserNonUniqueUsername, id='auth.W004', ) ] self.assertEqual(errors, expected)
def _setup_django(): try: import django django.setup() from django.core.checks import run_checks run_checks() except ImportError as error: logging.error('Found %s in environment, but couldn\'t import django: %s', DJANGO_SETTINGS_ENV_VAR, error) raise
def test_system_checks(): import django if django.VERSION >= (1, 7, 0): from django.core import checks if django.VERSION >= (1, 8, 0): assert not checks.run_checks(include_deployment_checks=False), "Some Django system checks failed" else: assert not checks.run_checks(), "Some Django system checks failed"
def validate_models(self): self.django_setup() try: from django.core.checks import run_checks except ImportError: # django < 1.7 from django.core.management.validation import get_validation_errors s = StringIO() num_errors = get_validation_errors(s, None) if num_errors: raise RuntimeError( 'One or more Django models did not validate:\n{0}'.format( s.getvalue())) else: run_checks()
def test_compatibility(self): """ Checks that an error is raised: - if an incompatible database is configured - if an incompatible cache is configured as ``CACHALOT_CACHE`` """ def get_error(object_path): return Error('`%s` is not compatible with django-cachalot.' % object_path, id='cachalot.E001') incompatible_database = { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'non_existent_db', } incompatible_cache = { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'cache_table' } with self.settings(DATABASES={'default': incompatible_database}): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, [get_error(incompatible_database['ENGINE'])]) with self.settings(CACHES={'default': incompatible_cache}): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, [get_error(incompatible_cache['BACKEND'])]) with self.settings(DATABASES={'default': incompatible_database}, CACHES={'default': incompatible_cache}): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, [get_error(incompatible_database['ENGINE']), get_error(incompatible_cache['BACKEND'])]) compatible_database = { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'non_existent_db.sqlite3', } compatible_cache = { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', } with self.settings(DATABASES={'default': compatible_database, 'secondary': incompatible_database}): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, [get_error(incompatible_database['ENGINE'])]) with self.settings(CACHES={'default': compatible_cache, 'secondary': incompatible_cache}): errors = run_checks(tags=[Tags.compatibility]) self.assertListEqual(errors, [])
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 '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)
def runtests(*test_args): if not settings.configured: settings.configure(**DEFAULT_SETTINGS) django.setup() parent = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, parent) from django.core import checks try: from django.test.runner import DiscoverRunner runner_class = DiscoverRunner test_args = ["pinax.{{ app_name }}.tests"] except ImportError: from django.test.simple import DjangoTestSuiteRunner runner_class = DjangoTestSuiteRunner test_args = ["tests"] checks = checks.run_checks() if checks: sys.exit(checks) failures = runner_class(verbosity=1, interactive=True, failfast=False).run_tests(test_args) sys.exit(failures)
def runtests(*test_args): if not settings.configured: settings.configure(**DEFAULT_SETTINGS) # Compatibility with Django 1.7's stricter initialization if hasattr(django, "setup"): django.setup() parent = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, parent) from django.core import checks try: from django.test.runner import DiscoverRunner runner_class = DiscoverRunner test_args = ["pinax.referrals.tests"] except ImportError: from django.test.simple import DjangoTestSuiteRunner runner_class = DjangoTestSuiteRunner test_args = ["tests"] checks = checks.run_checks() if checks: sys.exit(checks) failures = runner_class(verbosity=1, interactive=True, failfast=False).run_tests(test_args) sys.exit(failures)
def test_check_invalid_base_form_class(self): class BadFormClass: pass invalid_base_form = checks.Error( "ValidatedPage.base_form_class does not extend WagtailAdminPageForm", hint="Ensure that wagtail.admin.tests.test_edit_handlers.BadFormClass extends WagtailAdminPageForm", obj=ValidatedPage, id='wagtailadmin.E001') invalid_edit_handler = checks.Error( "ValidatedPage.get_edit_handler().get_form_class() does not extend WagtailAdminPageForm", hint="Ensure that the EditHandler for ValidatedPage creates a subclass of WagtailAdminPageForm", obj=ValidatedPage, id='wagtailadmin.E002') with mock.patch.object(ValidatedPage, 'base_form_class', new=BadFormClass): errors = checks.run_checks() # ignore CSS loading errors (to avoid spurious failures on CI servers that # don't build the CSS) errors = [e for e in errors if e.id != 'wagtailadmin.W001'] # Errors may appear out of order, so sort them by id errors.sort(key=lambda e: e.id) self.assertEqual(errors, [invalid_base_form, invalid_edit_handler])
def test_middleware_factory_functions_supported(self): messages = run_checks() if django.VERSION[:2] >= (2, 0): self.assertEqual(messages, []) else: self.assertEqual(messages[0].id, '1_10.W001')
def test_multi_null_country(self): try: class MultiNullCountry(models.Model): countries = fields.CountryField(multiple=True, null=True, blank=True) class MultiNullCountryNoBlank(models.Model): countries = fields.CountryField(multiple=True, null=True) errors = checks.run_checks() self.assertEqual([e.id for e in errors], ["django_countries.E100"] * 2) errors_dict = dict((e.obj, e) for e in errors) self.assertFalse( "blank=True" in errors_dict[MultiNullCountry._meta.get_field("countries")].hint ) self.assertTrue( "blank=True" in errors_dict[ MultiNullCountryNoBlank._meta.get_field("countries") ].hint ) finally: from django.apps import apps test_config = apps.get_app_config("django_countries_tests") test_config.models.pop("multinullcountry") test_config.models.pop("multinullcountrynoblank")
def test_checks(self): django.setup() from django.core import checks all_issues = checks.run_checks() errors = [str(e) for e in all_issues if e.level >= checks.ERROR] if errors: self.fail('checks failed:\n' + '\n'.join(errors))
def test_model_signal(self): unresolved_references = post_init.unresolved_references.copy() post_init.connect(on_post_init, sender='missing-app.Model') post_init.connect(OnPostInit(), sender='missing-app.Model') errors = run_checks() expected = [ Error( "The 'on_post_init' function was connected to the 'post_init' " "signal with a lazy reference to the 'missing-app.Model' " "sender, which has not been installed.", hint=None, obj='model_validation.tests', id='signals.E001', ), Error( "An instance of the 'OnPostInit' class was connected to " "the 'post_init' signal with a lazy reference to the " "'missing-app.Model' sender, which has not been installed.", hint=None, obj='model_validation.tests', id='signals.E001', ) ] self.assertEqual(errors, expected) post_init.unresolved_references = unresolved_references
def check(self, app_configs=None, tags=None, display_num_errors=False, include_deployment_checks=False): """ Uses the system check framework to validate entire Django project. Raises CommandError for any serious message (error or critical errors). If there are only light messages (like warnings), they are printed to stderr and no exception is raised. """ all_issues = checks.run_checks( app_configs=app_configs, tags=tags, include_deployment_checks=include_deployment_checks, ) msg = "" visible_issue_count = 0 # excludes silenced warnings if all_issues: debugs = [e for e in all_issues if e.level < checks.INFO and not e.is_silenced()] infos = [e for e in all_issues if checks.INFO <= e.level < checks.WARNING and not e.is_silenced()] warnings = [e for e in all_issues if checks.WARNING <= e.level < checks.ERROR and not e.is_silenced()] errors = [e for e in all_issues if checks.ERROR <= e.level < checks.CRITICAL] criticals = [e for e in all_issues if checks.CRITICAL <= e.level] sorted_issues = [ (criticals, 'CRITICALS'), (errors, 'ERRORS'), (warnings, 'WARNINGS'), (infos, 'INFOS'), (debugs, 'DEBUGS'), ] for issues, group_name in sorted_issues: if issues: visible_issue_count += len(issues) formatted = ( color_style().ERROR(force_str(e)) if e.is_serious() else color_style().WARNING(force_str(e)) for e in issues) formatted = "\n".join(sorted(formatted)) msg += '\n%s:\n%s\n' % (group_name, formatted) if msg: msg = "System check identified some issues:\n%s" % msg if display_num_errors: if msg: msg += '\n' msg += "System check identified %s (%s silenced)." % ( "no issues" if visible_issue_count == 0 else "1 issue" if visible_issue_count == 1 else "%s issues" % visible_issue_count, len(all_issues) - visible_issue_count, ) if any(e.is_serious() and not e.is_silenced() for e in all_issues): raise CommandError(msg) elif msg and visible_issue_count: self.stderr.write(msg) elif msg: self.stdout.write(msg)
def test_is_anonymous_authenticated_methods(self): """ <User Model>.is_anonymous/is_authenticated must not be methods. """ class BadUser(AbstractBaseUser): username = models.CharField(max_length=30, unique=True) USERNAME_FIELD = 'username' def is_anonymous(self): return True def is_authenticated(self): return True errors = checks.run_checks(app_configs=self.apps.get_app_configs()) self.assertEqual(errors, [ checks.Critical( '%s.is_anonymous must be an attribute or property rather than ' 'a method. Ignoring this is a security issue as anonymous ' 'users will be treated as authenticated!' % BadUser, obj=BadUser, id='auth.C009', ), checks.Critical( '%s.is_authenticated must be an attribute or property rather ' 'than a method. Ignoring this is a security issue as anonymous ' 'users will be treated as authenticated!' % BadUser, obj=BadUser, id='auth.C010', ), ])
def test_checks_are_performed(self): admin.site.register(Song, MyAdmin) try: errors = checks.run_checks() expected = ['error!'] self.assertEqual(errors, expected) finally: admin.site.unregister(Song)
def test_cache_check_errors(self): errors = run_checks() error = Warning( msg=Messages.BACKEND_INVALID, hint=Hints.BACKEND_INVALID, id=Codes.BACKEND_INVALID, ) self.assertEqual([error], errors)
def test_non_clashing_custom_permissions(self): class Checked(models.Model): class Meta: permissions = [ ('my_custom_permission', 'Some permission'), ('other_one', 'Some other permission'), ] errors = checks.run_checks(self.apps.get_app_configs()) self.assertEqual(errors, [])
def test_models_check(self): self.maxDiff = None app_configs = [apps.get_app_config("testapp")] all_issues = checks.run_checks( app_configs=app_configs, tags=None, include_deployment_checks=False, ) self.assertListEqual(all_issues, [])
def test_generic_foreign_key_checks_are_performed(self): class MyGenericForeignKey(GenericForeignKey): def check(self, **kwargs): return ['performed!'] class Model(models.Model): content_object = MyGenericForeignKey() errors = checks.run_checks(app_configs=self.apps.get_app_configs()) self.assertEqual(errors, ['performed!'])
def test_generic_foreign_key_checks_are_performed(self): class MyGenericForeignKey(GenericForeignKey): def check(self, **kwargs): return ["performed!"] class Model(models.Model): content_object = MyGenericForeignKey() errors = checks.run_checks() self.assertEqual(errors, ["performed!"])
def test_cache_misconfiguration_produces_check_error(self): errors = run_checks() error = Error( msg=Messages.CACHE_INVALID, hint=Hints.CACHE_INVALID, obj=settings.CACHES, id=Codes.CACHE_INVALID, ) self.assertIn(error, errors)
def test_cache_missing_produces_check_error(self): errors = run_checks() error = Error( msg=Messages.CACHE_MISSING, hint=Hints.CACHE_MISSING, obj=settings.CACHES, id=Codes.CACHE_MISSING, ) self.assertIn(error, errors)
def test_no_collision_for_unmanaged_models(self): class Unmanaged(models.Model): class Meta: db_table = 'test_table' managed = False class Managed(models.Model): class Meta: db_table = 'test_table' self.assertEqual(checks.run_checks(app_configs=self.apps.get_app_configs()), [])
def test_no_collision_for_proxy_models(self): class Model(models.Model): class Meta: db_table = 'test_table' class ProxyModel(Model): class Meta: proxy = True self.assertEqual(Model._meta.db_table, ProxyModel._meta.db_table) self.assertEqual(checks.run_checks(app_configs=self.apps.get_app_configs()), [])
def test_custom_adminsite(self): class CustomAdminSite(admin.AdminSite): pass custom_site = CustomAdminSite() custom_site.register(Song, MyAdmin) try: errors = checks.run_checks() expected = ['error!'] self.assertEqual(errors, expected) finally: custom_site.unregister(Song)
def test_required_fields_is_list(self): "REQUIRED_FIELDS should be a list." errors = checks.run_checks() expected = [ checks.Error( "'REQUIRED_FIELDS' must be a list or tuple.", hint=None, obj=CustomUserNonListRequiredFields, id='auth.E001', ), ] self.assertEqual(errors, expected)
def test_checks_are_performed(self): class MyAdmin(admin.ModelAdmin): @classmethod def check(self, model, **kwargs): return ['error!'] admin.site.register(Song, MyAdmin) try: errors = checks.run_checks() expected = ['error!'] self.assertEqual(errors, expected) finally: admin.site.unregister(Song)
def test_collision_in_same_model(self): index = models.Index(fields=['id'], name='foo') class Model(models.Model): class Meta: indexes = [index, index] self.assertEqual( checks.run_checks(app_configs=self.apps.get_app_configs()), [ Error( "index name 'foo' is not unique for model check_framework.Model.", id='models.E029', ), ])
def performance(request): """Show performance tuning tips.""" if request.method == 'POST': return handle_dismiss(request) context = { 'checks': run_checks(include_deployment_checks=True), 'errors': ConfigurationError.objects.filter(ignored=False), 'queues': get_queue_stats().items(), 'menu_items': MENU, 'menu_page': 'performance', } return render(request, "manage/performance.html", context)
def test_model_name_max_length(self): model_name = 'X' * 94 model = type(model_name, (models.Model, ), {'__module__': self.__module__}) errors = checks.run_checks(self.apps.get_app_configs()) self.assertEqual(errors, [ checks.Error( "The name of model 'auth_tests.%s' must be at most 93 " "characters for its builtin permission codenames to be at " "most 100 characters." % model_name, obj=model, id='auth.E011', ), ])
def test_auto_created_inherited_parent_link(self): class Parent(models.Model): pass class Child(Parent): parent_ptr = models.OneToOneField(Parent, models.CASCADE, parent_link=True) self.assertEqual( checks.run_checks(app_configs=self.apps.get_app_configs()), [ Warning(self.msg, hint=self.hint, obj=Parent, id='models.W042'), ])
def test_no_collision_across_apps_interpolation(self, apps): constraint = models.CheckConstraint(check=models.Q(id__gt=0), name='%(app_label)s_%(class)s_foo') class Model1(models.Model): class Meta: app_label = 'basic' constraints = [constraint] class Model2(models.Model): class Meta: app_label = 'check_framework' constraints = [constraint] self.assertEqual(checks.run_checks(app_configs=apps.get_app_configs()), [])
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)
def test_check_missing_middleware_error(self): messages = run_checks() self.assertEqual( messages, [ Warning( "debug_toolbar.middleware.DebugToolbarMiddleware is " "missing from MIDDLEWARE.", hint="Add debug_toolbar.middleware.DebugToolbarMiddleware " "to MIDDLEWARE.", id="debug_toolbar.W001", ) ], )
def test_no_collision_across_apps_interpolation(self, apps): index = models.Index(fields=['id'], name='%(app_label)s_%(class)s_foo') class Model1(models.Model): class Meta: app_label = 'basic' constraints = [index] class Model2(models.Model): class Meta: app_label = 'check_framework' constraints = [index] self.assertEqual(checks.run_checks(app_configs=apps.get_app_configs()), [])
def test_missing_middleware(self): with self.settings( ** { MIDDLEWARE_SETTINGS_NAME: [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', ] }): messages = run_checks() self.assertTrue(len(messages) > 0) self.assertEqual(messages[0].id, 'speedinfo.W001')
def test_required_fields_is_list(self): "REQUIRED_FIELDS should be a list." from .custom_user import CustomUserNonListRequiredFields errors = checks.run_checks() expected = [ checks.Error( 'The REQUIRED_FIELDS must be a list or tuple.', hint=None, obj=CustomUserNonListRequiredFields, id='auth.E001', ), ] self.assertEqual(errors, expected)
def performance(request): """Show performance tuning tips.""" if request.method == "POST": return handle_dismiss(request) context = { "checks": run_checks(include_deployment_checks=True), "errors": ConfigurationError.objects.filter(ignored=False), "queues": get_queue_stats().items(), "menu_items": MENU, "menu_page": "performance", } return render(request, "manage/performance.html", context)
def test_verbose_name_max_length(self): class Checked(models.Model): class Meta: verbose_name = 'some ridiculously long verbose name that is out of control' * 5 errors = checks.run_checks(self.apps.get_app_configs()) self.assertEqual(errors, [ checks.Error( "The verbose_name of model 'auth_tests.Checked' must be at most 244 " "characters for its builtin permission names to be at most 255 characters.", obj=Checked, id='auth.E007', ), ])
def performance(request, admin_site): """Show performance tuning tips.""" if request.method == 'POST': return handle_dismiss(request) context = admin_site.each_context(request) context['checks'] = run_checks(include_deployment_checks=True) context['errors'] = ConfigurationError.objects.filter(ignored=False) return render( request, "admin/performance.html", context, )
def test_auto_created_inherited_pk(self): class Parent(models.Model): pass class Child(Parent): pass self.assertEqual( checks.run_checks(app_configs=self.apps.get_app_configs()), [ Warning(self.msg, hint=self.hint, obj=Parent, id="models.W042"), ], )
def test_username_partially_unique(self): class CustomUserPartiallyUnique(AbstractBaseUser): username = models.CharField(max_length=30) USERNAME_FIELD = 'username' class Meta: constraints = [ UniqueConstraint( fields=['username'], name='partial_username_unique', condition=Q(password__isnull=False), ), ] errors = checks.run_checks(app_configs=self.apps.get_app_configs()) self.assertEqual(errors, [ checks.Error( "'CustomUserPartiallyUnique.username' must be unique because " "it is named as the 'USERNAME_FIELD'.", obj=CustomUserPartiallyUnique, id='auth.E003', ), ]) with self.settings(AUTHENTICATION_BACKENDS=['my.custom.backend']): errors = checks.run_checks(app_configs=self.apps.get_app_configs()) self.assertEqual(errors, [ checks.Warning( "'CustomUserPartiallyUnique.username' is named as the " "'USERNAME_FIELD', but it is not unique.", hint=( 'Ensure that your authentication backend(s) can ' 'handle non-unique usernames.' ), obj=CustomUserPartiallyUnique, id='auth.W004', ), ])
def test_no_collision_abstract_model_interpolation(self): class AbstractModel(models.Model): name = models.CharField(max_length=20) class Meta: indexes = [models.Index(fields=['name'], name='%(app_label)s_%(class)s_foo')] abstract = True class Model1(AbstractModel): pass class Model2(AbstractModel): pass self.assertEqual(checks.run_checks(app_configs=self.apps.get_app_configs()), [])
def test_collision_in_same_model(self): class Model(models.Model): class Meta: constraints = [ models.CheckConstraint(check=models.Q(id__gt=0), name='foo'), models.CheckConstraint(check=models.Q(id__lt=100), name='foo'), ] self.assertEqual(checks.run_checks(app_configs=self.apps.get_app_configs()), [ Error( "constraint name 'foo' is not unique for model " "check_framework.Model.", id='models.E031', ), ])
def test_no_collision_abstract_model_interpolation(self): class AbstractModel(models.Model): class Meta: constraints = [ models.CheckConstraint(check=models.Q(id__gt=0), name='%(app_label)s_%(class)s_foo'), ] abstract = True class Model1(AbstractModel): pass class Model2(AbstractModel): pass self.assertEqual(checks.run_checks(app_configs=self.apps.get_app_configs()), [])
def test_field_check_errors(self): with self.settings(INSTALLED_APPS=settings.INSTALLED_APPS + ("broken_test_app", )): self.maxDiff = None app_configs = [apps.get_app_config("broken_test_app")] all_issues = checks.run_checks( app_configs=app_configs, tags=None, include_deployment_checks=False, ) self.assertListEqual([issue.id for issue in all_issues], [ 'compositefk.E001', 'compositefk.E002', 'compositefk.E003', 'compositefk.E003', 'compositefk.E004', 'compositefk.E006', 'compositefk.E005' ])
def test_clashing_default_permissions(self): class Checked(models.Model): class Meta: permissions = [('change_checked', 'Can edit permission (duplicate)')] errors = checks.run_checks(self.apps.get_app_configs()) self.assertEqual(errors, [ checks.Error( "The permission codenamed 'change_checked' clashes with a builtin " "permission for model 'auth_tests.Checked'.", obj=Checked, id='auth.E005', ), ])
def test_warning_when_unique_true_on_fk(self): class FKUniqueTrue(models.Model): fk_field = models.ForeignKey(Foo, unique=True) expected_warnings = [ checks.Warning( 'Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.', hint= 'ForeignKey(unique=True) is usually better served by a OneToOneField.', obj=FKUniqueTrue.fk_field.field, id='fields.W342', ) ] warnings = checks.run_checks() self.assertEqual(warnings, expected_warnings)
def test_check_admin(self) -> None: errors = run_checks() self.assertEqual( errors, [ Error( "The model tests.UnregisteredModel is not registered with " "an admin site.", hint="Register the model in tests.admin or ignore this " "error by adding either checkadmin.ignore() or " "the CHECK_ADMIN_IGNORED_MODELS settings.", obj=UnregisteredModel, ) ], )
def test_username_non_unique(self): "A non-unique USERNAME_FIELD should raise a model validation error." from .custom_user import CustomUserNonUniqueUsername errors = checks.run_checks() expected = [ checks.Error( ('The CustomUserNonUniqueUsername.username field must be ' 'unique because it is pointed to by USERNAME_FIELD.'), hint=None, obj=CustomUserNonUniqueUsername, id='auth.E003', ), ] self.assertEqual(errors, expected)
def test_check_gzip_middleware_error(self): messages = run_checks() self.assertEqual( messages, [ Error( "debug_toolbar.middleware.DebugToolbarMiddleware occurs " "before django.middleware.gzip.GZipMiddleware in " "MIDDLEWARE_CLASSES.", hint="Move debug_toolbar.middleware.DebugToolbarMiddleware " "to after django.middleware.gzip.GZipMiddleware in " "MIDDLEWARE_CLASSES.", ), ] )
def test_username_non_unique(self): "A non-unique USERNAME_FIELD should raise a model validation error." from .custom_user import CustomUserNonUniqueUsername errors = checks.run_checks() expected = [ checks.Error( ("'CustomUserNonUniqueUsername.username' must be " "unique because it is named as the 'USERNAME_FIELD'."), hint=None, obj=CustomUserNonUniqueUsername, id='auth.E003', ), ] self.assertEqual(errors, expected)
def test_username_not_in_required_fields(self): "USERNAME_FIELD should not appear in REQUIRED_FIELDS." from .custom_user import CustomUserBadRequiredFields errors = checks.run_checks() expected = [ checks.Error( ("The field named as the 'USERNAME_FIELD' for a custom user model " "must not be included in 'REQUIRED_FIELDS'."), hint=None, obj=CustomUserBadRequiredFields, id='auth.E002', ), ] self.assertEqual(errors, expected)
def configuration_health_check(checks=None): # Run deployment checks if needed if checks is None: checks = run_checks(include_deployment_checks=True) checks_dict = {check.id: check for check in checks} criticals = { "weblate.E002", "weblate.E003", "weblate.E007", "weblate.E009", "weblate.E012", "weblate.E013", "weblate.E014", "weblate.E015", "weblate.E017", "weblate.E018", "weblate.E019", "weblate.C023", "weblate.C029", "weblate.C030", "weblate.C031", "weblate.C032", "weblate.E034", "weblate.C035", "weblate.C036", } removals = [] existing = { error.name: error for error in ConfigurationError.objects.all() } for check_id in criticals: if check_id in checks_dict: check = checks_dict[check_id] if check_id in existing: error = existing[check_id] if error.message != check.msg: error.message = check.msg error.save(update_fields=["message"]) else: ConfigurationError.objects.create(name=check_id, message=check.msg) elif check_id in existing: removals.append(check_id) if removals: ConfigurationError.objects.filter(name__in=removals).delete()
def test_username_non_unique_with_custom_backend(self): """ A non-unique USERNAME_FIELD should raise an error only if we use the default authentication backend. Otherwise, an warning should be raised. """ errors = checks.run_checks() expected = [ checks.Warning( ("'CustomUserNonUniqueUsername.username' is named as " "the 'USERNAME_FIELD', but it is not unique."), hint=('Ensure that your authentication backend(s) can handle ' 'non-unique usernames.'), obj=CustomUserNonUniqueUsername, id='auth.W004', ) ] self.assertEqual(errors, expected)
def test_cache_middleware_position(self): with self.settings( ** { MIDDLEWARE_SETTINGS_NAME: [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', 'speedinfo.middleware.ProfilerMiddleware', ] }): messages = run_checks() self.assertTrue(len(messages) > 0) self.assertEqual(messages[0].id, 'speedinfo.E001')
def test_multi_null_country(self): class MultiNullCountry(models.Model): countries = fields.CountryField(multiple=True, null=True, blank=True) class MultiNullCountryNoBlank(models.Model): countries = fields.CountryField(multiple=True, null=True) errors = checks.run_checks() self.assertEqual([e.id for e in errors], ['django_countries.E100'] * 2) errors_dict = dict((e.obj, e) for e in errors) self.assertFalse('blank=True' in errors_dict[ MultiNullCountry._meta.get_field('countries')].hint) self.assertTrue('blank=True' in errors_dict[ MultiNullCountryNoBlank._meta.get_field('countries')].hint)