如何测试登录过程?

moo*_*eep 9 django validation django-forms django-authentication django-testing

我正在使用Django 1.6开发一个Web应用程序,我要求用户使用我的登录表单登录.我想编写一个测试用例来测试登录用户的过程.

我确实成功获得了一个工作登录页面,这意味着我能够登录.以下步骤解释了我的设置.但是,为此过程编写测试用例确实失败了.在这一点上,我既不能在测试中发现错误,也不确定这种方法是否有意义.有人能帮我吗?

更新:在此期间我注意到,我的表单错误消息太不明确了.该问题似乎是由表单字段验证步骤失败的空表单字段引起的.当我将错误添加{{ form.errors }}到模板时,响应包含以下内容(格式不太好):

<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>
Run Code Online (Sandbox Code Playgroud)

我仍然不确定如何最合理地测试这个程序.我是Django的新手,也是它测试框架的哲学.可能是,这个问题不直接落入Django测试框架的范围,在这个框架中,模型,视图和表单(看似)是相互分离的(看似)?这个测试是否属于独立测试套件进行黑盒/功能测试的领域,例如,使用Selenium?


我开始是这样的:

  1. 开始了一个新项目,如下所示:

    django-admin.py startproject login_test
    
    Run Code Online (Sandbox Code Playgroud)
  2. 添加了一个条目login_test/urls.py,像这样:

    urlpatterns = patterns('',
        url(r'^login/$', 'django.contrib.auth.views.login'),
        url(r'^admin/', include(admin.site.urls)),
    )
    
    Run Code Online (Sandbox Code Playgroud)
  3. 制作模板/home/moooeeeep/login_test/templates/registration/login.html,如下:

    {% 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 %}
    
    Run Code Online (Sandbox Code Playgroud)
  4. 将模板目录添加到TEMPLATE_DIRSlogin_test/settings.py,如下所示:

    TEMPLATE_DIRS = (
        '/home/moooeeeep/login_test/templates/',
    )
    
    Run Code Online (Sandbox Code Playgroud)
  5. 同步数据库以获取与auth相关的表,并添加了这样的超级用户:

    python manage.py syncdb
    
    Run Code Online (Sandbox Code Playgroud)

如果我没有错过任何一步,此时我可以登录我的网站.登录后,我会显示我的用户名,如果没有,我会看到表单,如果登录失败,则会显示错误消息.


然而,我的测试用例在提交正确的帖子数据后,会看到失败的登录响应,用户没有登录.

这是我的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)
Run Code Online (Sandbox Code Playgroud)

这是输出:

$ 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'...
Run Code Online (Sandbox Code Playgroud)

这是我的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/',
)
Run Code Online (Sandbox Code Playgroud)

moo*_*eep 11

我发现我传递的post参数是错误的(字典不能解压缩).我还需要了解,我需要在发送数据后遵循发布请求发出的重定向.然后我的登录测试工作(虽然重定向的目标页面尚不存在).

这是我更新的测试用例:

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)
Run Code Online (Sandbox Code Playgroud)

这是输出:

$ python manage.py test
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.196s

OK
Destroying test database for alias 'default'...
Run Code Online (Sandbox Code Playgroud)


nkh*_*eys 8

你不想检查"is_active"布尔值,你想要检查

response.context['user'].is_authenticated
Run Code Online (Sandbox Code Playgroud)

请参阅:https://docs.djangoproject.com/en/1.3/topics/auth/#django.contrib.auth.models.User.is_active

和:https://docs.djangoproject.com/en/1.3/topics/auth/#django.contrib.auth.models.User.is_authenticated

  • 您可以尝试使用self.client.login(username =“”,password =“”)来确保用户能够登录。 (2认同)