我正在尝试为Django应用程序编写集成测试,以测试密码是否已从其他API更改。但是,在调用密码更改API后,测试新密码不起作用。
我在这里做的是:我通过休息呼叫将密码更改为johnjohn
,然后尝试检查密码是否实际更改
我的单元测试文件
import json
import urllib
import urllib2
import requests
from django.contrib.auth.models import User
from django.test import TestCase
from adaptors.redis_class import DjangoRedis
class PasswordChange(TestCase):
def setUp(self):
User.objects.create_user(username='john', email='john@john.com', password='john')
# class for redis access
r = DjangoRedis()
r.set("email:john@john.com", '0' * 40, ex=3600)
r.set('0' * 40, "email:john@john.com", ex=3600)
def test_change_password(self):
# Fake url I set through redis
url = 'http://127.0.0.1:8000/reset/' + '0' * 40 + '/'
r = requests.get(url)
csrf_token = r.content.split('csrf_token')[1].split('"')[2]
payload = {'csrfmiddlewaretoken': csrf_token, 'payload': json.dumps({'password': 'johnjohn'})}
headers = {'Cookie': 'csrftoken=' + csrf_token}
data = urllib.urlencode(payload)
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
json_res = json.loads(response.read())
# This doesn't fail
self.assertEqual(json_res['password_changed'], True)
u = User.objects.get(username='john')
# This fails
self.assertEqual(u.check_password('johnjohn'),True)
我的观点
import hashlib
import random
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404
from django.http import JsonResponse
from django.shortcuts import render
from django.views.generic import View
from adaptors.redis_class import DjangoRedis
from constants import PASSWORD_RESET
from tasks import send_email
from util.rest import get_payload
class ResetPage(View):
def post(self, requests, reset_token):
r = DjangoRedis()
token = r.get(reset_token)
if token is None:
return JsonResponse({"token": False})
payload = get_payload(requests.POST)
try:
email = token.split(':')[1].lower()
u = User.objects.get(email=email)
u.set_password(payload['password'])
u.save()
r.delete(reset_token)
r.delete('email:' + email)
return JsonResponse({'password_changed': True})
except ValueError:
return JsonResponse({"password_changed": False, 'error': "can't get your email from the database (E01)"})
except ObjectDoesNotExist:
return JsonResponse({"password_changed": False, 'error': "User doesn't exist (E02)"})
def get(self, requests, reset_token):
r = DjangoRedis()
if not r.get(reset_token):
raise Http404
return render(requests, "login/reset.html", {'token': reset_token})
unittest文件在rest_pass_login_tests.py
目录中称为unittests
。
我使用以下命令运行它。
./manage.py test unittests/ --pattern="rest_pass_login_tests.py"
当我通过浏览器正常测试时,密码更改工作正常。但是,当我尝试通过unittest检查密码是否已更改时,我收到的密码无效。
我做错了什么?
答案 0 :(得分:1)
我使用dev服务器来运行unittests。当我更改密码时,我实际上是发布到开发服务器而不是测试服务器。
这是我的新单元测试
import json
from django.contrib.auth.models import User
from django.test import Client
from django.test import TestCase
from adaptors.redis_class import DjangoRedis
class PasswordChange(TestCase):
def setUp(self):
User.objects.create_user(username='john', email='john@john.com', password='john')
r = DjangoRedis()
r.set("email:john@john.com", '0' * 40, ex=3600)
r.set('0' * 40, "email:john@john.com", ex=3600)
def test_change_password(self):
c = Client()
payload = {'payload': json.dumps({'password': 'johnjohn'})}
url = '/reset/' + '0' * 40 + '/'
res = c.post(url, payload)
res = res.json()
self.assertEqual(res['password_changed'], True)
u = User.objects.get(username='john')
self.assertEqual(u.check_password('johnjohn'), True)
如果您要使用selenium
IDE,请确保StaticLiveServerTestCase
而不是unittest固有。关注this example。另外,不要忘记将此变量self.base_url
更改为self.live_server_url
这是我的setUp方法
self.base_url = self.live_server_url
感谢fips,koterpillar帮助我进入IRC频道,感谢aks在我的评论下。
答案 1 :(得分:0)
您没有像您的观点所期望的那样制作http post
。
以下是使用urllib2制作帖子的方法:Making a POST call instead of GET using urllib2
但是,既然你已经使用requests
模块,为什么不这样做呢:
url = 'http://127.0.0.1:8000/reset/' + '0' * 40 + '/'
payload = {'csrfmiddlewaretoken': csrf_token, 'payload': json.dumps({'password': 'johnjohn'})}
headers = {'Cookie': 'csrftoken=' + csrf_token}
r = requests.post(url, data=payload, headers=headers)
json_res = json.loads(r.content)
也许可以尝试调试/打印json_res
的值来检查是否还有其他意外情况。
另请注意,这是一个集成测试,因为您正在通过http进行测试,因此您的urls.py,views.py甚至settings.py正在作为其中的一部分进行测试。