python - form - django test login



login() dans le framework de test Django (2)

Il peut souvent être utile d'utiliser un backend d'authentification personnalisé qui ignore toute sorte d'authentification lors des tests:

from django.contrib.auth import get_user_model

class TestcaseUserBackend(object):
    def authenticate(self, testcase_user=None):
        return testcase_user

    def get_user(self, user_id):
        User = get_user_model()
        return User.objects.get(pk=user_id)

Ensuite, pendant les tests, ajoutez yourapp.auth_backends.TestcaseUserBackend à votre AUTHENTICATION_BACKENDS :

AUTHENTICATION_BACKENDS = [
    "akindi.testing.auth_backends.TestcaseUserBackend",
]

Ensuite, pendant les tests, vous pouvez simplement appeler:

from django.contrib.auth import login
user = User.objects.get(…)
login(testcase_user=user)

J'ai commencé à utiliser le framework de test de Django et tout fonctionnait correctement jusqu'à ce que je commence à tester les pages authentifiées.

Par souci de simplicité, disons que ceci est un test:

class SimpleTest(TestCase):
    def setUp(self):
        user = User.objects.create_user('temporary', '[email protected]', 'temporary')

    def test_secure_page(self):
        c = Client()
        print c.login(username='temporary', password='temporary')
        response = c.get('/users/secure/', follow=True)
        user = User.objects.get(username='temporary')
        self.assertEqual(response.context['email'], '[email protected]')

Après avoir exécuté ce test, il échoue et je vois que la valeur de retour de login () renvoie True , mais response.content est redirigé vers la page de connexion (si la connexion échoue, l'authentification du décorateur redirige vers la page de connexion). J'ai mis un point d'arrêt dans le décorateur qui fait l'authentification:

def authenticate(user):
    if user.is_authenticated():
        return True
    return False

et il retourne vraiment faux . La ligne 4 de test_secure_page () récupère correctement l'utilisateur.

Ceci est la fonction d'affichage:

@user_passes_test(authenticate, login_url='/users/login')
def secure(request):
    user = request.user
    return render_to_response('secure.html', {'email': user.email})

Bien sûr, si je tente de me connecter via l'application (en dehors des tests), tout fonctionne correctement.


Answer #1

Le problème est que vous ne transmettez pas RequestContext à votre modèle.

En outre, vous devriez probablement utiliser le décorateur login_required et le client intégré à la classe TestCase .

Je le réécrirais comme ceci:

#views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.contrib.auth import get_user_model

@login_required(login_url='/users/login')
def secure(request):
    user = request.user
    return render(request, 'secure.html', {'email': user.email})



#tests.py
class SimpleTest(TestCase):
    def setUp(self):
        User = get_user_model()
        user = User.objects.create_user('temporary', '[email protected]', 'temporary')

    def test_secure_page(self):
        User = get_user_model()
        self.client.login(username='temporary', password='temporary')
        response = self.client.get('/manufacturers/', follow=True)
        user = User.objects.get(username='temporary')
        self.assertEqual(response.context['email'], '[email protected]')




login