如何测试登录过程?

时间:2014-03-17 14:51:59

标签: 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>

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


我是这样开始的:

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

    django-admin.py startproject login_test
    
  2. login_test/urls.py添加了一个条目,如下所示:

    urlpatterns = patterns('',
        url(r'^login/$', 'django.contrib.auth.views.login'),
        url(r'^admin/', include(admin.site.urls)),
    )
    
  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 %}
    
  4. 将模板目录添加到TEMPLATE_DIRS中的login_test/settings.py,如下所示:

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

    python manage.py syncdb
    
  6. 如果我没有错过任何一步,此时我可以登录我的网站。登录后我会显示我的用户名,如果没有,我会看到表单,如果登录失败,它会显示错误信息。


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

    这是我的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)
    

    这是输出:

    $ 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'...
    

    这是我的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/',
    )
    

2 个答案:

答案 0 :(得分:9)

我发现我传递的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)

这是输出:

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

OK
Destroying test database for alias 'default'...

答案 1 :(得分:6)

你不想检查&#34; is_active&#34;布尔值,你想要检查

response.context['user'].is_authenticated

请参阅: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