如何测试登录过程?
Posted
技术标签:
【中文标题】如何测试登录过程?【英文标题】:How to test login process? 【发布时间】:2014-04-22 20:19:09 【问题描述】:我正在使用 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)的独立测试套件的领域?
我是这样开始的:
开始一个新项目,像这样:
django-admin.py startproject login_test
在login_test/urls.py
中添加了一个条目,如下所示:
urlpatterns = patterns('',
url(r'^login/$', 'django.contrib.auth.views.login'),
url(r'^admin/', include(admin.site.urls)),
)
在/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 %
将模板目录添加到login_test/settings.py
中的TEMPLATE_DIRS
,像这样:
TEMPLATE_DIRS = (
'/home/moooeeeep/login_test/templates/',
)
同步数据库以获取与身份验证相关的表,并添加一个超级用户,如下所示:
python manage.py syncdb
如果我没有错过任何一步,此时我可以登录我的网站。登录时,我会显示我的用户名,如果没有,我会看到表单,如果登录失败,还会显示一条错误消息。
然而,我的测试用例,在提交正确的帖子数据后,会看到登录失败的响应,用户没有登录。
这是我的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/',
)
【问题讨论】:
您能检查一下response.context['user']
中的内容吗?
@alecxe 这是AnonymousUser。
好的,请显示你的设置,尤其是我关心AUTHENTICATION_BACKENDS
设置。
@alecxe 请看我的编辑。显然这是一个表单验证问题。错误消息抱怨空表单字段。
我不确定为什么你认为表单是罪魁祸首,login
视图在测试期间被调用。您能否显示您的设置(请同时包括您的中间件)?谢谢。
【参考方案1】:
你不想检查“is_active”布尔值,你想检查
response.context['user'].is_authenticated
见: https://docs.djangoproject.com/en/dev/topics/auth/default/#authentication-in-web-requests
和: https://docs.djangoproject.com/en/dev/ref/contrib/auth/
【讨论】:
无济于事,因为request.context
中有一个AnonymousUser
。
在这种情况下不会有帮助,但是一旦您解决了 AnonymouseUser 问题(即用户未登录),那么您仍然需要检查 is_authenticated 而不是 is_active
您可以尝试使用 self.client.login(username="", password="") 以确保用户能够登录。
两个链接都没有找到!
@Mahdimehrabi 没有找到这些链接我并不感到惊讶,这个答案已有 7 年历史,适用于非常旧的 Django 版本【参考方案2】:
我发现我传递的post参数是错误的(字典一定不能解包)。我还需要了解,我需要在发送数据后遵循 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'...
【讨论】:
以上是关于如何测试登录过程?的主要内容,如果未能解决你的问题,请参考以下文章