From 2f4c47177d8a11e62e61166da8dde30f6a796c59 Mon Sep 17 00:00:00 2001 From: Velda Kiara <32552296+VeldaKiara@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:22:18 +0300 Subject: [PATCH] 'djdt' is not a registered namespace #1405 (#1889) * updated the change to the changes.rst file * solution to djdt registered namespace,update docs, system checks and tests * removing test in the if statements * Add basic test to example app and example_test to make commands. * Update check for toolbar and tests. * update check using with, combine the four tests to one, update default config * update installation files and remove patch from namespace check * Clean-up the changelog * Add docs for the IS_RUNNING_TESTS setting Co-authored-by: Matthias Kestenholz * Change the code for the toolbar testing error to E001 * Reduce number of .settings calls and document config update. --------- Co-authored-by: Tim Schilling Co-authored-by: Matthias Kestenholz --- Makefile | 3 +++ debug_toolbar/apps.py | 28 +++++++++++++++++++++--- debug_toolbar/settings.py | 2 ++ docs/changes.rst | 10 +++++++++ docs/configuration.rst | 11 ++++++++++ docs/installation.rst | 6 +++++ example/settings.py | 20 ++++++++++++++--- example/test_views.py | 12 ++++++++++ example/urls.py | 7 +++++- tests/settings.py | 4 +++- tests/test_checks.py | 46 ++++++++++++++++++++++++++++++++++++--- 11 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 example/test_views.py diff --git a/Makefile b/Makefile index 1600496e5..24b59ab95 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,9 @@ example: --noinput --username="$(USER)" --email="$(USER)@mailinator.com" python example/manage.py runserver +example_test: + python example/manage.py test example + test: DJANGO_SETTINGS_MODULE=tests.settings \ python -m django test $${TEST_ARGS:-tests} diff --git a/debug_toolbar/apps.py b/debug_toolbar/apps.py index 05cd35ae3..a2e977d84 100644 --- a/debug_toolbar/apps.py +++ b/debug_toolbar/apps.py @@ -3,7 +3,7 @@ from django.apps import AppConfig from django.conf import settings -from django.core.checks import Warning, register +from django.core.checks import Error, Warning, register from django.middleware.gzip import GZipMiddleware from django.utils.module_loading import import_string from django.utils.translation import gettext_lazy as _ @@ -177,7 +177,7 @@ def check_panels(app_configs, **kwargs): return errors -@register() +@register def js_mimetype_check(app_configs, **kwargs): """ Check that JavaScript files are resolving to the correct content type. @@ -208,7 +208,29 @@ def js_mimetype_check(app_configs, **kwargs): return [] -@register() +@register +def debug_toolbar_installed_when_running_tests_check(app_configs, **kwargs): + """ + Check that the toolbar is not being used when tests are running + """ + if not settings.DEBUG and dt_settings.get_config()["IS_RUNNING_TESTS"]: + return [ + Error( + "The Django Debug Toolbar can't be used with tests", + hint="Django changes the DEBUG setting to False when running " + "tests. By default the Django Debug Toolbar is installed because " + "DEBUG is set to True. For most cases, you need to avoid installing " + "the toolbar when running tests. If you feel this check is in error, " + "you can set `DEBUG_TOOLBAR_CONFIG['IS_RUNNING_TESTS'] = False` to " + "bypass this check.", + id="debug_toolbar.E001", + ) + ] + else: + return [] + + +@register def check_settings(app_configs, **kwargs): errors = [] USER_CONFIG = getattr(settings, "DEBUG_TOOLBAR_CONFIG", {}) diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py index 1df24527d..868d50a90 100644 --- a/debug_toolbar/settings.py +++ b/debug_toolbar/settings.py @@ -1,3 +1,4 @@ +import sys import warnings from functools import lru_cache @@ -42,6 +43,7 @@ "SQL_WARNING_THRESHOLD": 500, # milliseconds "OBSERVE_REQUEST_CALLBACK": "debug_toolbar.toolbar.observe_request", "TOOLBAR_LANGUAGE": None, + "IS_RUNNING_TESTS": "test" in sys.argv, "UPDATE_ON_FETCH": False, } diff --git a/docs/changes.rst b/docs/changes.rst index 5e2b4081f..997a997f2 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -22,6 +22,16 @@ Pending ``DEBUG_TOOLBAR_SETTINGS``. * Add a note on the profiling panel about using Python 3.12 and later about needing ``--nothreading`` +* Added ``IS_RUNNING_TESTS`` setting to allow overriding the + ``debug_toolbar.E001`` check to avoid including the toolbar when running + tests. +* Fixed the bug causing ``'djdt' is not a registered namespace`` and updated + docs to help in initial configuration while running tests. +* Added a link in the installation docs to a more complete installation + example in the example app. +* Added check to prevent the toolbar from being installed when tests + are running. +* Added test to example app and command to run the example app's tests. 4.3.0 (2024-02-01) ------------------ diff --git a/docs/configuration.rst b/docs/configuration.rst index b7db25900..2af0b7fa4 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -72,6 +72,17 @@ Toolbar options The toolbar searches for this string in the HTML and inserts itself just before. +* ``IS_RUNNING_TESTS`` + + Default: ``"test" in sys.argv`` + + This setting whether the application is running tests. If this resolves to + ``True``, the toolbar will prevent you from running tests. This should only + be changed if your test command doesn't include ``test`` or if you wish to + test your application with the toolbar configured. If you do wish to test + your application with the toolbar configured, set this setting to + ``False``. + .. _RENDER_PANELS: * ``RENDER_PANELS`` diff --git a/docs/installation.rst b/docs/installation.rst index 1f2e1f119..3644bdd5c 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -81,6 +81,11 @@ Add ``"debug_toolbar"`` to your ``INSTALLED_APPS`` setting: "debug_toolbar", # ... ] +.. note:: Check out the configuration example in the + `example app + `_ + to learn how to set up the toolbar to function smoothly while running + your tests. 4. Add the URLs ^^^^^^^^^^^^^^^ @@ -99,6 +104,7 @@ Add django-debug-toolbar's URLs to your project's URLconf: This example uses the ``__debug__`` prefix, but you can use any prefix that doesn't clash with your application's URLs. + 5. Add the Middleware ^^^^^^^^^^^^^^^^^^^^^ diff --git a/example/settings.py b/example/settings.py index d2bd57387..1508b5a29 100644 --- a/example/settings.py +++ b/example/settings.py @@ -1,12 +1,14 @@ """Django settings for example project.""" import os +import sys BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # Quick-start development settings - unsuitable for production + SECRET_KEY = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" DEBUG = True @@ -22,11 +24,9 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - "debug_toolbar", ] MIDDLEWARE = [ - "debug_toolbar.middleware.DebugToolbarMiddleware", "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", @@ -61,7 +61,6 @@ WSGI_APPLICATION = "example.wsgi.application" -DEBUG_TOOLBAR_CONFIG = {"ROOT_TAG_EXTRA_ATTRS": "data-turbo-permanent hx-preserve"} # Cache and database @@ -97,3 +96,18 @@ } STATICFILES_DIRS = [os.path.join(BASE_DIR, "example", "static")] + + +# Only enable the toolbar when we're in debug mode and we're +# not running tests. Django will change DEBUG to be False for +# tests, so we can't rely on DEBUG alone. +ENABLE_DEBUG_TOOLBAR = DEBUG and "test" not in sys.argv +if ENABLE_DEBUG_TOOLBAR: + INSTALLED_APPS += [ + "debug_toolbar", + ] + MIDDLEWARE += [ + "debug_toolbar.middleware.DebugToolbarMiddleware", + ] + # Customize the config to support turbo and htmx boosting. + DEBUG_TOOLBAR_CONFIG = {"ROOT_TAG_EXTRA_ATTRS": "data-turbo-permanent hx-preserve"} diff --git a/example/test_views.py b/example/test_views.py new file mode 100644 index 000000000..c3a8b96b0 --- /dev/null +++ b/example/test_views.py @@ -0,0 +1,12 @@ +# Add tests to example app to check how the toolbar is used +# when running tests for a project. +# See https://github.com/jazzband/django-debug-toolbar/issues/1405 + +from django.test import TestCase +from django.urls import reverse + + +class ViewTestCase(TestCase): + def test_index(self): + response = self.client.get(reverse("home")) + assert response.status_code == 200 diff --git a/example/urls.py b/example/urls.py index da52601f8..7569a57f9 100644 --- a/example/urls.py +++ b/example/urls.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.contrib import admin from django.urls import include, path from django.views.generic import TemplateView @@ -33,5 +34,9 @@ ), path("admin/", admin.site.urls), path("ajax/increment", increment, name="ajax_increment"), - path("__debug__/", include("debug_toolbar.urls")), ] + +if settings.ENABLE_DEBUG_TOOLBAR: + urlpatterns += [ + path("__debug__/", include("debug_toolbar.urls")), + ] diff --git a/tests/settings.py b/tests/settings.py index b3c281242..269900c18 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -126,5 +126,7 @@ DEBUG_TOOLBAR_CONFIG = { # Django's test client sets wsgi.multiprocess to True inappropriately - "RENDER_PANELS": False + "RENDER_PANELS": False, + # IS_RUNNING_TESTS must be False even though we're running tests because we're running the toolbar's own tests. + "IS_RUNNING_TESTS": False, } diff --git a/tests/test_checks.py b/tests/test_checks.py index d04f8fc87..827886db1 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -1,8 +1,11 @@ from unittest.mock import patch -from django.core.checks import Warning, run_checks +from django.core.checks import Error, Warning, run_checks from django.test import SimpleTestCase, override_settings +from debug_toolbar import settings as dt_settings +from debug_toolbar.apps import debug_toolbar_installed_when_running_tests_check + class ChecksTestCase(SimpleTestCase): @override_settings( @@ -97,7 +100,7 @@ def test_panels_is_empty(self): hint="Set DEBUG_TOOLBAR_PANELS to a non-empty list in your " "settings.py.", id="debug_toolbar.W005", - ) + ), ], ) @@ -236,8 +239,45 @@ def test_check_w007_invalid(self, mocked_guess_type): ], ) + def test_debug_toolbar_installed_when_running_tests(self): + with self.settings(DEBUG=True): + # Update the config options because self.settings() + # would require redefining DEBUG_TOOLBAR_CONFIG entirely. + dt_settings.get_config()["IS_RUNNING_TESTS"] = True + errors = debug_toolbar_installed_when_running_tests_check(None) + self.assertEqual(len(errors), 0) + + dt_settings.get_config()["IS_RUNNING_TESTS"] = False + errors = debug_toolbar_installed_when_running_tests_check(None) + self.assertEqual(len(errors), 0) + with self.settings(DEBUG=False): + dt_settings.get_config()["IS_RUNNING_TESTS"] = False + errors = debug_toolbar_installed_when_running_tests_check(None) + self.assertEqual(len(errors), 0) + + dt_settings.get_config()["IS_RUNNING_TESTS"] = True + errors = debug_toolbar_installed_when_running_tests_check(None) + self.assertEqual( + errors, + [ + Error( + "The Django Debug Toolbar can't be used with tests", + hint="Django changes the DEBUG setting to False when running " + "tests. By default the Django Debug Toolbar is installed because " + "DEBUG is set to True. For most cases, you need to avoid installing " + "the toolbar when running tests. If you feel this check is in error, " + "you can set `DEBUG_TOOLBAR_CONFIG['IS_RUNNING_TESTS'] = False` to " + "bypass this check.", + id="debug_toolbar.E001", + ) + ], + ) + @override_settings( - DEBUG_TOOLBAR_CONFIG={"OBSERVE_REQUEST_CALLBACK": lambda request: False} + DEBUG_TOOLBAR_CONFIG={ + "OBSERVE_REQUEST_CALLBACK": lambda request: False, + "IS_RUNNING_TESTS": False, + } ) def test_observe_request_callback_specified(self): errors = run_checks()