How to test the login process?

I am developing a web application using Django 1.6 where I need users to log in to my account. I want to write a test case that checks the user login procedure.

I managed to get a working login page, that is, I was able to login. The following steps explain my installation. However, writing a test case for this procedure failed. At the moment, I can’t detect an error in my test and I'm not sure that this approach makes sense first of all. Can anybody help me?

Update: In the meantime, I noticed that the form error message was too non-specific. Apparently, the problem is caused by empty form fields that do not perform any stage of form validation. When I add errors {{ form.errors }} to the template, the response contains the following (formatted a little less nicely):

 <ul class="errorlist"> <li>username <ul class="errorlist"> <li>This field is required.</li> </ul> </li> <li>password <ul class="errorlist"> <li>This field is required.</li> </ul> </li> </ul> 

I'm still not sure how the most reasonable way to test this procedure. I am completely new to Django and the testing philosophy. Maybe this question does not fall directly into the scope of Django testing, where models, views, and forms (apparently) are intended for testing, rather than being separated from each other? This test more likely falls into the scope of an independent set of tests performing the black core / functional testing, for example, using Selenium?


I started like this:

  • Launched a new project, for example:

     django-admin.py startproject login_test 
  • added an entry in login_test/urls.py , for example:

     urlpatterns = patterns('', url(r'^login/$', 'django.contrib.auth.views.login'), url(r'^admin/', include(admin.site.urls)), ) 
  • compiled the template /home/moooeeeep/login_test/templates/registration/login.html , for example:

     {% if form.errors %} <p>Your username and password didn't match. Please try again.</p> {% endif %} {% if not user.is_active %} <form method="post" action="{% url 'django.contrib.auth.views.login' %}"> {% csrf_token %} {{ form.as_p }} <button type="submit">Login</button> <input type="hidden" name="next" value="{% url 'django.contrib.auth.views.login' %}" /> </form> {% else %} <p>You are logged in as <strong>{{ user.username }}</strong>.</p> {% endif %} 
  • added the template directory in TEMPLATE_DIRS in login_test/settings.py , for example:

     TEMPLATE_DIRS = ( '/home/moooeeeep/login_test/templates/', ) 
  • Synchronize the database to get auth-related tables, and add the superuser as follows:

     python manage.py syncdb 

If I had not missed a single step, I could log in to my site. When I log in, I get my displayed username, if I don’t see the form, if the login fails, it also displays an error message.


My test case, however, after sending the correct messages, receives a message about an unsuccessful response at the entrance, while the user is not logged in.

Here is my login_test/tests.py :

 from django.contrib.auth.models import User from django.contrib.auth import SESSION_KEY from django.test import TestCase class LogInTest(TestCase): def setUp(self): self.credentials = { 'username': 'testuser', 'password': 'secret'} User.objects.create_user(**self.credentials) def test_login(self): # login response = self.client.post('/login/', **self.credentials) # should be logged in now, fails however self.assertTrue(response.context['user'].is_active) 

Here's the conclusion:

 $ python manage.py test Creating test database for alias 'default'... F ====================================================================== FAIL: test_login (login_test.tests.LogInTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/moooeeeep/login_test/login_test/tests.py", line 16, in test_login self.assertTrue(response.context['user'].is_active) AssertionError: False is not true ---------------------------------------------------------------------- Ran 1 test in 0.008s FAILED (failures=1) Destroying test database for alias 'default'... 

Here is my login_test/settings.py :

 import os BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '+6e-6t8dnl$75fx%=7y$+4ipo&i=kvw(p*963p37)7o$1-)30u' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True TEMPLATE_DEBUG = True INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ) MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) ROOT_URLCONF = 'login_test.urls' WSGI_APPLICATION = 'login_test.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } TEMPLATE_DIRS = ( '/home/moooeeeep/login_test/templates/', ) 
+6
source share
2 answers

I found out that my message parameter transition was wrong (the dictionary should not be unpacked). I also needed to find out that I needed to follow the redirect issued after the request after sending the data. Then my login worked (although the page that was the redirecting target does not exist yet).

Here is my updated test case:

 from django.contrib.auth.models import User from django.test import TestCase class LogInTest(TestCase): def setUp(self): self.credentials = { 'username': 'testuser', 'password': 'secret'} User.objects.create_user(**self.credentials) def test_login(self): # send login data response = self.client.post('/login/', self.credentials, follow=True) # should be logged in now self.assertTrue(response.context['user'].is_active) 

Here's the conclusion:

 $ python manage.py test Creating test database for alias 'default'... . ---------------------------------------------------------------------- Ran 1 test in 0.196s OK Destroying test database for alias 'default'... 
+7
source
+4
source

All Articles