2011-09-09 16 views
27

Empecé a usar el marco de prueba de Django, y todo funcionaba bien hasta que comencé a probar las páginas autenticadas.inicio de sesión() en el marco de prueba de Django

En aras de la simplicidad, digamos que esta es una prueba:

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]') 

después de ejecutar esta prueba, se produce un error, y veo que la impresión de valor de retorno de inicio de sesión() devuelve verdadera, pero response.content se redirige a la página de inicio de sesión (si el inicio de sesión falla, el decorador de autenticación redirige a la página de inicio de sesión). He puesto un punto de quiebre en el decorador que hace la autenticación:

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

y realmente devuelve Falso . La línea 4 en test_secure_page() recupera correctamente al usuario.

Esta es la función de vista:

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

Por supuesto, si intento iniciar sesión a través de la aplicación (fuera de la prueba), todo funciona bien.

+1

Y publique el código de la vista que está probando. –

+0

@ S.Lott No estaba probando mi página de inicio de sesión (aunque lo intenté también, pero eso tampoco funciona), sino el resto de la parte "segura" del sistema. Por esa razón, traté de usar login(). – kevin

+1

@kevin. El problema es que la publicación para iniciar sesión crea una cookie que luego utiliza el cliente. Sin cookies, sin acceso seguro. AFAIK, la función 'login()' no crea la cookie y la devuelve al cliente. ¿Puedes tratar de reproducir los ejemplos en la documentación de Django y ver si funcionan para ti? –

Respuesta

25

El problema es que no está pasando RequestContext a su plantilla.

Además, probablemente deba usar el decorador login_required y el cliente incorporado en la clase TestCase.

me gustaría volver a escribir así:

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

@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 = User.objects.create_user('temporary', '[email protected]', 'temporary') 

    def test_secure_page(self): 
     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]') 
+1

¿Por qué crees que no pasar RequestContext debería ser un problema (se da contexto a render_to_response())? Funciona fuera del marco de prueba cuando esto se invoca desde el navegador (por cierto, traté de pasar RequestContext, pero sucede lo mismo). Además, la autenticación ocurre antes de que se ingrese la vista. Intenté también @login_required y el cliente de la clase TestCase, pero sucede lo mismo. – kevin

+0

Lo hice funcionar cambiando: self.assertEqual (response.context ['user']. Email, '[email protected]') – cor

10

A menudo puede ser útil el uso de un motor de autenticación personalizado que elude el cualquier tipo de autenticación durante la prueba:

from django.contrib.auth.models import User 

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

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

Luego, durante las pruebas , añadir a su yourapp.auth_backends.TestcaseUserBackendAUTHENTICATION_BACKENDS:

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

Entonces, durin g pruebas, simplemente puede llamar a:

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

Excelente respuesta. –

+1

obteniendo ': login() obtuvo un argumento de palabra clave inesperado 'testcase_user'' alguna idea? – intelis

+0

¿Estás seguro de que 'login' es de' django.contrib.auth' (ver publicación editada)?¿Y está seguro de que el servidor se está agregando correctamente? –

Cuestiones relacionadas