Opened 8 years ago

Closed 7 years ago

#26961 closed Cleanup/optimization (fixed)

Run admin checks if DEBUG is False

Reported by: Adam Johnson Owned by: nobody
Component: contrib.admin Version: 1.9
Severity: Normal Keywords: checks
Cc: me@… Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In our CI system we run call_command('check') during tests and manage.py check before deployment. Two bugs crept through recently thanks to broken admin checks.

This is because the contrib.admin checks don't run unless DEBUG = True, which is not recommended for tests or production, so we never saw these checks break.

The commit that moved the checks from custom validation to the check framework hints at why this it was historically only when DEBUG = True at https://github.com/django/django/commit/4ad1eb1c14b629cf5bcfd253ed40e875f1bddd47#diff-57866af2aff590165ffe4967107424fdL69 :

Don't import the humongous validation code unless required

This isn't valid reason with the check framework since all the code is imported anyway when assigning checks_class on BaseModelAdmin, the only memory now saved is that the list of failing checks isn't instantiated.

I'd argue the DEBUG requirement should be removed

Change History (15)

comment:2 by Tim Graham, 8 years ago

Patch needs improvement: set
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

A couple tests need to be fixed and a mention in the release notes could be useful.

comment:3 by Tim Graham, 8 years ago

Summary: Admin check does not run unless DEBUG = TrueRun admin checks if DEBUG is False

comment:4 by Adam Johnson, 8 years ago

Should I change the 1.10 release notes?

comment:5 by Tim Graham, 8 years ago

1.10 is at release candidate stage and only receiving fixes for release blockers. Please target 1.11.

comment:6 by Adam Johnson, 8 years ago

Thanks, wasn't entirely sure if small changes like this were still accepted.

comment:7 by Adam Johnson, 8 years ago

One of the failures is interesting:

  File "/home/jenkins/workspace/pull-requests-trusty/database/mysql/label/trusty-pr/python/python2.7/tests/model_validation/tests.py", line 23, in test_models_validate
    management.call_command("check", stdout=six.StringIO())

It looks like this test calls check which runs against everything in memory. Needs refactoring?

Also this is partly caused by the way the admin checks run - they get executed during site.register and append all the errors to a global list of failures. This backfires in the wake of multiple AdminSites which get created during the tests, with ModelAdmin classes registered and deregistered, leaving the errors they created at each register in the list. Any idea why the list isn't just calculated dynamically when check is called?

comment:8 by Tim Graham, 8 years ago

Yes, I guess that first test isn't ideal (see its origin in a19e9d80ffa10f8da43addcaa4ddd440beee8a4d). I guess it could be removed if #25415 is completed.

I can't advise on the design of the admin checks but from what I remember, the implementation seemed a bit odd when I was looking through it, so if you want to try to refactor it, that would be welcome.

comment:9 by Adam Johnson, 8 years ago

I've re-factored the admin checks to be dynamically created, by keeping track of all the AdminSite references that exist, and calling check on each individually when the admin app check function is called. That in itself didn't seem to cause any errors.

I've also fixed a number of checks that were failing for the model and admin classes defined in tests, if only I'd finished #25415 and made tests run checks again!

Another thing I had to do was make CheckMessage succeed in comparisons with non-CheckMessage classes because some tests return plain strings from their temporary check functions and then these don't compare with real check messages that come out, and the test crashes unhelpfully.

I'm still working a couple of failures that seem broken due to the lack of integration between checks and the app registry. Some tests fail with checks from apps that have been unloaded through override_settings(INSTALLED_APPS=. Unfortunately the app registry doesn't reset the check registry, and it can't really because the interface of checks allows not only to be registered during AppConfig.ready but just at import time, so clearing the check registry on app registry reload would unload those checks and then not re-register them...

The exact failures are:

======================================================================
ERROR: test_migrate_with_system_checks (migrations.test_commands.MigrateTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 329, in run
    testMethod()
  File "/Users/adamj/Documents/Projects/django/django/test/utils.py", line 209, in inner
    return func(*args, **kwargs)
  File "/Users/adamj/Documents/Projects/django/tests/migrations/test_commands.py", line 65, in test_migrate_with_system_checks
    call_command('migrate', skip_checks=False, no_color=True, stdout=out)
  File "/Users/adamj/Documents/Projects/django/django/core/management/__init__.py", line 130, in call_command
    return command.execute(*args, **defaults)
  File "/Users/adamj/Documents/Projects/django/django/core/management/base.py", line 353, in execute
    self.check()
  File "/Users/adamj/Documents/Projects/django/django/core/management/base.py", line 431, in check
    raise SystemCheckError(msg)
SystemCheckError: SystemCheckError: System check identified some issues:

ERRORS:
<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[4]' refers to 'chap__book__promo', which does not refer to a Field.
<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[4]' refers to 'chap__book__promo', which does not refer to a Field.
<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[5]' refers to 'chap__book__promo__name', which does not refer to a Field.
<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[5]' refers to 'chap__book__promo__name', which does not refer to a Field.


======================================================================
FAIL: test_system_exit (user_commands.tests.CommandTests)
Exception raised in a command should raise CommandError with
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 329, in run
    testMethod()
  File "/Users/adamj/Documents/Projects/django/tests/user_commands/tests.py", line 60, in test_system_exit
    self.assertIn("CommandError", stderr.getvalue())
  File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 803, in assertIn
    self.fail(self._formatMessage(msg, standardMsg))
  File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 410, in fail
    raise self.failureException(msg)
AssertionError: 'CommandError' not found in "\x1b[31;1mSystemCheckError: System check identified some issues:\n\x1b[0m\nERRORS:\n\x1b[31;1m<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[4]' refers to 'chap__book__promo', which does not refer to a Field.\x1b[0m\n\x1b[31;1m<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[4]' refers to 'chap__book__promo', which does not refer to a Field.\x1b[0m\n\x1b[31;1m<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[5]' refers to 'chap__book__promo__name', which does not refer to a Field.\x1b[0m\n\x1b[31;1m<class 'admin_views.admin.ChapterXtra1Admin'>: (admin.E116) The value of 'list_filter[5]' refers to 'chap__book__promo__name', which does not refer to a Field.\x1b[0m\n"

On its own, running the admin_views tests with a call_command('check') inserted, the checks pass. It seems that something is affecting these admin_views models before test_migrate_with_system_checks then re-runs the checks and finds them failing. I can't figure it out :/

comment:10 by Adam Johnson, 8 years ago

OK I couldn't figure out an easy way around the above confusion. I thing it's straight up wrong to run 'check' with INSTALLED_APPS overridden. As such I've deleted or modified the few tests that did so.

comment:11 by Tim Graham, 8 years ago

I'm not sure it's acceptable to remove regressions tests such as the one added in 93deb1691eb27dc89135511fb0c10e077c8baca7 without offering some replacement.

comment:12 by Adam Johnson, 8 years ago

Fair, though the bug corrected in 93deb1691eb27dc89135511fb0c10e077c8baca7 is a pretty rare one though.

Afaict the main reason tests are overriding INSTALLED_APPS before doing call_command('check') is because there are so many check errors in other test apps. Which leads me back to fixing all those as part of #25415...

comment:13 by Tim Graham <timograham@…>, 7 years ago

In cd86f03:

Refs #26961 -- Fixed invalid ModelAdmins in tests.

comment:14 by Tim Graham, 7 years ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

The final bit of this work is on the PR for #27673.

comment:15 by Tim Graham <timograham@…>, 7 years ago

Resolution: fixed
Status: newclosed

In 9daf8c43:

Fixed #26961 -- Made admin checks run when DEBUG=False.

Note: See TracTickets for help on using tickets.
Back to Top