Opened 10 years ago

Closed 10 years ago

#21466 closed Bug (invalid)

override_settings(LOGIN_URL=…) does not work when not first test

Reported by: Jannis Vajen Owned by: nobody
Component: Testing framework Version: 1.6
Severity: Normal Keywords: settings
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Overriding LOGIN_URL in the tests does not work when another test is run beforehand.

from django.test import TestCase
from django.test.utils import override_settings
from django.core.urlresolvers import reverse
from django.conf import settings


class OverrideSettingsTest(TestCase):
    def test_a(self):
        """
        Toggle this test by commenting it out and see whether test_b() passes.
        """
        response = self.client.get(reverse("harmless-view"))
        self.assertEqual(response.status_code, 301)

    @override_settings(LOGIN_URL="/THIS_IS_FINE/")
    def test_b(self):
        # settings appear to be overridden as expected
        self.assertEqual(settings.LOGIN_URL, "/THIS_IS_FINE/")
        response = self.client.get(reverse("redirect-to-login"))

        # The following assertion fails only when test_a() is run.
        self.assertRedirects(response, "/THIS_IS_FINE/",
            status_code=301,
            target_status_code=404
        )

    def test_c(self):
        response = self.client.get(reverse("harmless-view"))
        self.assertEqual(response.status_code, 301)
.F.
======================================================================
FAIL: test_b (override_bug.tests.OverrideSettingsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "django/test/utils.py", line 224, in inner
    return test_func(*args, **kwargs)
  File "override_bug/override_bug/tests.py", line 24, in test_b
    target_status_code=404
  File "django/test/testcases.py", line 617, in assertRedirects
    (url, expected_url))
AssertionError: Response redirected to 'http://testserver/THIS/SHOULD/BE/OVERRIDDEN/IN/THE/TEST/', expected 'http://testserver/THIS_IS_FINE/'

----------------------------------------------------------------------
Ran 3 tests in 0.031s

Attachments (1)

sample_project (50.0 KB ) - added by Jannis Vajen 10 years ago.
An example project which exhibits the bug (filetype: tar)

Download all attachments as: .zip

Change History (6)

by Jannis Vajen, 10 years ago

Attachment: sample_project added

An example project which exhibits the bug (filetype: tar)

comment:1 by Claude Paroz, 10 years ago

Resolution: invalid
Status: newclosed

I'm almost sure the problem is related to the way you are using settings.LOGIN_URL. In your sample project, it is used as a parameter of the as_view call in your URLConf, that means that it will be defined once and for all requests at import time.
You can workaround this issue by subclassing RedirectView and overriding get_redirect_url() so that when settings.LOGIN_URL changes your view can take that change into account. I don't think we can do anything on Django's side.

comment:2 by Jannis Vajen, 10 years ago

Sorry for opening this ticket. You're right that this has nothing to do with Django.

I used django-braces' LoginRequiredMixin which sets settings.LOGIN_URL at import time and replicated this bug in my example project without further reflecting upon this issue.

comment:3 by matthewf@…, 10 years ago

I think I'm hitting the same issue as well. In my project, I have set a variable called REGISTRATION_ENABLED. However, when I try to override this setting in my tests, it's never read. Changing the setting beforehand in my settings.py makes the test pass, however. This is how it's used in my tests:

def test_auth(self):
        """
        Test that a user can register using the API, login and logout
        """
        # test registration workflow
        submit = {
            'username': 'Otto',
            'password': 'password',
            'first_name': 'first_name',
            'last_name': 'last_name',
            'email': 'email@email.com',
            'is_superuser': False,
            'is_staff': False,
        }
        url = '/api/auth/register'
        response = self.client.post(url, json.dumps(submit), content_type='application/json')
        self.assertEqual(response.status_code, 201)
        # test disabled registration
        with self.settings(REGISTRATION_ENABLED=False):
            submit['username'] = 'anothernewuser'
            response = self.client.post(url, json.dumps(submit), content_type='application/json')
            self.assertEqual(response.status_code, 403)

And the code block in my views:

class HasRegistrationAuth(permissions.BasePermission):
    """
    Checks to see if registration is enabled
    """
    def has_permission(self, request, view):
        return settings.REGISTRATION_ENABLED

Note that I'm using https://github.com/tomchristie/django-rest-framework in my application.

comment:4 by Matthew Fisher, 10 years ago

Resolution: invalid
Status: closednew

apologies, I forgot to add the output of my tests!

$ ./manage.py test api
Creating test database for alias 'default'...
.......F....................................................
======================================================================
FAIL: test_auth (api.tests.test_auth.AuthTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/api/tests/test_auth.py", line 64, in test_auth
    self.assertEqual(response.status_code, 403)
AssertionError: 201 != 403

----------------------------------------------------------------------
Ran 60 tests in 29.056s

FAILED (failures=1)
Destroying test database for alias 'default'...

When i modify the setting to False in settings.py, the test passes without failure.

Last edited 10 years ago by Matthew Fisher (previous) (diff)

comment:5 by Tim Graham, 10 years ago

Resolution: invalid
Status: newclosed

I think it's more likely that your use of override_settings() is invalid. Please be sure you've read the caveats in the documentation and ask questions using our support channels. If after doing those setps you still believe you've found a bug, please open a new ticket, thanks.

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