You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Django/doc/accounts/tests.py

277 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 导入Django测试所需的核心类Client模拟HTTP请求、RequestFactory创建请求对象、TestCase测试基类
from django.test import Client, RequestFactory, TestCase
# 导入reverse通过URL名称生成路径用于测试中定位接口
from django.urls import reverse
# 导入timezone处理时间相关字段用于创建测试数据
from django.utils import timezone
# 导入翻译工具,用于处理国际化文本(测试中未直接使用,但保持原导入)
from django.utils.translation import gettext_lazy as _
# 导入需要测试的自定义模型:用户模型、文章模型、分类模型
from accounts.models import BlogUser
from blog.models import Article, Category
# 导入项目工具函数(如获取当前站点、加密、缓存操作等)
from djangoblog.utils import *
# 导入当前模块的工具函数(如验证码处理)
from . import utils
# 定义账户相关测试类继承Django的TestCase提供测试框架支持
class AccountTest(TestCase):
def setUp(self):
"""
测试初始化方法,在每个测试方法执行前自动调用
用于创建共用的测试对象,避免代码重复
"""
# 创建测试客户端用于模拟用户发送HTTP请求
self.client = Client()
# 创建请求工厂,用于生成原始请求对象(按需使用)
self.factory = RequestFactory()
# 创建普通测试用户用户名test、邮箱admin@admin.com、密码12345678
self.blog_user = BlogUser.objects.create_user(
username="test",
email="admin@admin.com",
password="12345678"
)
# 定义测试用的新密码,后续忘记密码测试中使用
self.new_test = "xxx123--="
def test_validate_account(self):
"""测试账户基础功能超级用户创建、登录验证、admin访问、内容创建与管理"""
# 获取当前站点域名(测试中未实际使用,保持原逻辑)
site = get_current_site().domain
# 创建超级用户拥有admin管理权限
user = BlogUser.objects.create_superuser(
email="liangliangyy1@gmail.com",
username="liangliangyy1",
password="qwer!@#$ggg")
# 通过用户名查询刚创建的超级用户,验证创建成功
testuser = BlogUser.objects.get(username='liangliangyy1')
# 使用测试客户端模拟超级用户登录
loginresult = self.client.login(
username='liangliangyy1',
password='qwer!@#$ggg')
# 断言登录成功返回True
self.assertEqual(loginresult, True)
# 模拟访问admin后台页面
response = self.client.get('/admin/')
# 断言admin页面访问成功状态码200
self.assertEqual(response.status_code, 200)
# 创建测试分类:设置名称、创建时间、修改时间并保存
category = Category()
category.name = "categoryaaa"
category.creation_time = timezone.now()
category.last_modify_time = timezone.now()
category.save()
# 创建测试文章:关联作者(超级用户)和分类,设置标题、内容、类型、状态并保存
article = Article()
article.title = "nicetitleaaa"
article.body = "nicecontentaaa"
article.author = user
article.category = category
article.type = 'a' # 假设'a'代表普通文章类型
article.status = 'p' # 假设'p'代表已发布状态
article.save()
# 模拟访问文章的admin管理页面通过文章模型的get_admin_url方法获取路径
response = self.client.get(article.get_admin_url())
# 断言文章管理页面访问成功状态码200
self.assertEqual(response.status_code, 200)
def test_validate_register(self):
"""测试用户注册流程:注册请求、注册后用户存在性、邮箱验证、登录与权限升级、内容管理"""
# 注册前断言邮箱为user123@user.com的用户不存在初始状态
self.assertEquals(
0, len(
BlogUser.objects.filter(
email='user123@user.com')))
# 模拟发送注册请求向account:register接口提交用户名、邮箱、两次一致的密码
response = self.client.post(reverse('account:register'), {
'username': 'user1233',
'email': 'user123@user.com',
'password1': 'password123!q@wE#R$T',
'password2': 'password123!q@wE#R$T',
})
# 注册后断言邮箱为user123@user.com的用户存在注册成功
self.assertEquals(
1, len(
BlogUser.objects.filter(
email='user123@user.com')))
# 获取刚注册的用户,生成邮箱验证链接(使用项目加密逻辑生成签名)
user = BlogUser.objects.filter(email='user123@user.com')[0]
sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id))) # 双重SHA256加密签名
path = reverse('accounts:result') # 验证结果页的URL路径
url = '{path}?type=validation&id={id}&sign={sign}'.format(
path=path, id=user.id, sign=sign) # 拼接完整验证URL
# 模拟访问邮箱验证链接
response = self.client.get(url)
# 断言验证页面访问成功状态码200
self.assertEqual(response.status_code, 200)
# 模拟刚注册的用户登录
self.client.login(username='user1233', password='password123!q@wE#R$T')
# 升级用户权限为超级用户便于测试admin功能
user = BlogUser.objects.filter(email='user123@user.com')[0]
user.is_superuser = True # 设为超级用户
user.is_staff = True # 允许登录admin
user.save()
# 删除侧边栏缓存(项目自定义缓存操作,测试中保持原逻辑)
delete_sidebar_cache()
# 创建测试分类(用于后续创建文章)
category = Category()
category.name = "categoryaaa"
category.creation_time = timezone.now()
category.last_modify_time = timezone.now()
category.save()
# 创建测试文章(关联升级权限后的用户)
article = Article()
article.category = category
article.title = "nicetitle333"
article.body = "nicecontentttt"
article.author = user
article.type = 'a'
article.status = 'p'
article.save()
# 模拟访问文章的admin管理页面
response = self.client.get(article.get_admin_url())
self.assertEqual(response.status_code, 200)
# 模拟用户登出
response = self.client.get(reverse('account:logout'))
# 断言登出请求响应正常允许301/302重定向或200成功
self.assertIn(response.status_code, [301, 302, 200])
# 登出后尝试访问文章admin页面应被拒绝或重定向
response = self.client.get(article.get_admin_url())
self.assertIn(response.status_code, [301, 302, 200])
# 模拟使用错误密码登录(密码不匹配)
response = self.client.post(reverse('account:login'), {
'username': 'user1233',
'password': 'password123'
})
# 断言登录请求响应正常(无论成功失败,状态码合法)
self.assertIn(response.status_code, [301, 302, 200])
# 错误登录后尝试访问文章admin页面应被拒绝或重定向
response = self.client.get(article.get_admin_url())
self.assertIn(response.status_code, [301, 302, 200])
def test_verify_email_code(self):
"""测试邮箱验证码验证逻辑:正确验证码验证成功,错误邮箱验证失败"""
# 定义测试邮箱和生成随机验证码
to_email = "admin@admin.com"
code = generate_code() # 调用工具函数生成验证码
# 存储验证码(关联邮箱,用于后续验证)
utils.set_code(to_email, code)
# 发送验证邮件(测试中仅执行流程,不实际校验邮件发送结果)
utils.send_verify_email(to_email, code)
# 验证1使用正确的邮箱和验证码断言无错误返回验证成功
err = utils.verify("admin@admin.com", code)
self.assertEqual(err, None)
# 验证2使用错误的邮箱与存储的验证码不匹配断言返回错误信息字符串类型
err = utils.verify("admin@123.com", code)
self.assertEqual(type(err), str)
def test_forget_password_email_code_success(self):
"""测试获取忘记密码验证码的成功场景:提交正确邮箱,返回成功响应"""
# 模拟向account:forget_password_code接口提交正确邮箱
resp = self.client.post(
path=reverse("account:forget_password_code"),
data=dict(email="admin@admin.com")
)
# 断言请求成功状态码200且返回内容为"ok"(表示验证码发送成功)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.content.decode("utf-8"), "ok")
def test_forget_password_email_code_fail(self):
"""测试获取忘记密码验证码的失败场景:无邮箱、邮箱格式错误"""
# 失败场景1不提交邮箱空数据
resp = self.client.post(
path=reverse("account:forget_password_code"),
data=dict()
)
# 断言返回"错误的邮箱"(参数缺失)
self.assertEqual(resp.content.decode("utf-8"), "错误的邮箱")
# 失败场景2提交格式错误的邮箱admin@com不符合标准格式
resp = self.client.post(
path=reverse("account:forget_password_code"),
data=dict(email="admin@com")
)
# 断言返回"错误的邮箱"(格式校验失败)
self.assertEqual(resp.content.decode("utf-8"), "错误的邮箱")
def test_forget_password_email_success(self):
"""测试忘记密码重置成功场景:提交正确验证码和新密码,密码修改生效"""
# 生成验证码并关联测试用户的邮箱(模拟用户已获取验证码)
code = generate_code()
utils.set_code(self.blog_user.email, code)
# 构造忘记密码重置请求数据:新密码(两次一致)、用户邮箱、正确验证码
data = dict(
new_password1=self.new_test,
new_password2=self.new_test,
email=self.blog_user.email,
code=code,
)
# 模拟发送密码重置请求
resp = self.client.post(
path=reverse("account:forget_password"),
data=data
)
# 断言重置成功重定向到结果页状态码302
self.assertEqual(resp.status_code, 302)
# 验证密码是否真的修改成功:查询用户并校验新密码
blog_user = BlogUser.objects.filter(
email=self.blog_user.email,
).first() # 获取用户实例
self.assertNotEqual(blog_user, None) # 断言用户存在
# 使用check_password方法验证新密码是否匹配Django内置密码校验自动处理哈希
self.assertEqual(blog_user.check_password(data["new_password1"]), True)
def test_forget_password_email_not_user(self):
"""测试忘记密码重置失败场景:使用不存在的邮箱"""
# 构造请求数据:新密码、不存在的邮箱、任意验证码
data = dict(
new_password1=self.new_test,
new_password2=self.new_test,
email="123@123.com",
code="123456",
)
# 模拟发送密码重置请求
resp = self.client.post(
path=reverse("account:forget_password"),
data=data
)
# 断言请求响应正常页面返回错误提示状态码200
self.assertEqual(resp.status_code, 200)
def test_forget_password_email_code_error(self):
"""测试忘记密码重置失败场景:验证码错误"""
# 生成正确验证码并关联用户邮箱,但请求时提交错误验证码
code = generate_code()
utils.set_code(self.blog_user.email, code)
data = dict(
new_password1=self.new_test,
new_password2=self.new_test,
email=self.blog_user.email,
code="111111", # 错误的验证码
)
# 模拟发送密码重置请求
resp = self.client.post(
path=reverse("account:forget_password"),
data=data
)
# 断言请求响应正常页面返回验证码错误提示状态码200
self.assertEqual(resp.status_code, 200)