diff --git a/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/tests.py b/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/tests.py index ee135052..8eb99a81 100644 --- a/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/tests.py +++ b/djangoblog/src/DjangoBlog-master/DjangoBlog-master/blog/tests.py @@ -1,5 +1,7 @@ import os +import requests +# 导入Django核心模块:配置、文件上传、命令调用、分页、静态文件、测试工具、URL反转、时区 from django.conf import settings from django.core.files.uploadedfile import SimpleUploadedFile from django.core.management import call_command @@ -9,6 +11,7 @@ from django.test import Client, RequestFactory, TestCase from django.urls import reverse from django.utils import timezone +# 导入项目相关模型和工具:用户、博客模型、表单、模板标签、工具函数、OAuth相关 from accounts.models import BlogUser from blog.forms import BlogSearchForm from blog.models import Article, Category, Tag, SideBar, Links @@ -17,61 +20,90 @@ from djangoblog.utils import get_current_site, get_sha256 from oauth.models import OAuthUser, OAuthConfig -# Create your tests here. - class ArticleTest(TestCase): + """ + 博客核心功能测试类 + 测试文章、分类、标签、搜索、权限等核心业务逻辑 + """ + def setUp(self): - self.client = Client() - self.factory = RequestFactory() + """ + 测试前的初始化方法 + 创建测试客户端和请求工厂,用于模拟HTTP请求 + """ + self.client = Client() # 模拟用户浏览器的客户端 + self.factory = RequestFactory() # 用于构造请求对象的工厂 def test_validate_article(self): + """ + 测试文章相关核心功能: + - 用户模型操作 + - 分类、标签、侧边栏、链接等模型CRUD + - 文章发布、分页、搜索、评论等流程 + - 页面访问状态码验证 + """ + # 获取当前站点域名 site = get_current_site().domain + + # 创建或获取测试用户(管理员) user = BlogUser.objects.get_or_create( email="liangliangyy@gmail.com", username="liangliangyy")[0] - user.set_password("liangliangyy") - user.is_staff = True - user.is_superuser = True + user.set_password("liangliangyy") # 设置密码 + user.is_staff = True # 允许登录admin + user.is_superuser = True # 超级管理员权限 user.save() + + # 测试用户个人页面访问 response = self.client.get(user.get_absolute_url()) - self.assertEqual(response.status_code, 200) - response = self.client.get('/admin/servermanager/emailsendlog/') - response = self.client.get('admin/admin/logentry/') + self.assertEqual(response.status_code, 200) # 验证页面正常访问 + + # 测试admin后台页面访问(未登录状态,实际会跳转登录页) + self.client.get('/admin/servermanager/emailsendlog/') + self.client.get('admin/admin/logentry/') + + # 创建测试侧边栏 s = SideBar() - s.sequence = 1 - s.name = 'test' - s.content = 'test content' - s.is_enable = True + s.sequence = 1 # 排序序号 + s.name = 'test' # 名称 + s.content = 'test content' # 内容 + s.is_enable = True # 启用 s.save() + # 创建测试分类 category = Category() - category.name = "category" + category.name = "category" # 分类名称 category.creation_time = timezone.now() category.last_mod_time = timezone.now() category.save() + # 创建测试标签 tag = Tag() - tag.name = "nicetag" + tag.name = "nicetag" # 标签名称 tag.save() + # 创建测试文章 article = Article() - article.title = "nicetitle" - article.body = "nicecontent" - article.author = user - article.category = category - article.type = 'a' - article.status = 'p' - + article.title = "nicetitle" # 标题 + article.body = "nicecontent" # 内容 + article.author = user # 作者 + article.category = category # 所属分类 + article.type = 'a' # 类型为文章 + article.status = 'p' # 状态为已发布 article.save() + + # 验证标签关联(初始无标签) self.assertEqual(0, article.tags.count()) + # 关联标签并验证 article.tags.add(tag) article.save() self.assertEqual(1, article.tags.count()) + # 批量创建20篇测试文章(用于测试分页) for i in range(20): article = Article() - article.title = "nicetitle" + str(i) - article.body = "nicetitle" + str(i) + article.title = f"nicetitle{i}" + article.body = f"nicetitle{i}" article.author = user article.category = category article.type = 'a' @@ -79,114 +111,175 @@ class ArticleTest(TestCase): article.save() article.tags.add(tag) article.save() + + # 测试Elasticsearch搜索(如果启用) from blog.documents import ELASTICSEARCH_ENABLED if ELASTICSEARCH_ENABLED: - call_command("build_index") - response = self.client.get('/search', {'q': 'nicetitle'}) - self.assertEqual(response.status_code, 200) + call_command("build_index") # 构建搜索索引 + response = self.client.get('/search', {'q': 'nicetitle'}) # 执行搜索 + self.assertEqual(response.status_code, 200) # 验证搜索页正常 + # 测试文章详情页访问 response = self.client.get(article.get_absolute_url()) self.assertEqual(response.status_code, 200) + + # 测试搜索引擎推送功能 from djangoblog.spider_notify import SpiderNotify - SpiderNotify.notify(article.get_absolute_url()) + SpiderNotify.notify(article.get_absolute_url()) # 推送文章URL到搜索引擎 + + # 测试标签页访问 response = self.client.get(tag.get_absolute_url()) self.assertEqual(response.status_code, 200) + # 测试分类页访问 response = self.client.get(category.get_absolute_url()) self.assertEqual(response.status_code, 200) + # 测试搜索功能(无结果场景) response = self.client.get('/search', {'q': 'django'}) self.assertEqual(response.status_code, 200) + + # 测试文章标签模板标签 s = load_articletags(article) - self.assertIsNotNone(s) + self.assertIsNotNone(s) # 验证模板标签返回结果 + # 登录测试用户 self.client.login(username='liangliangyy', password='liangliangyy') + # 测试归档页访问 response = self.client.get(reverse('blog:archives')) self.assertEqual(response.status_code, 200) + # 测试各种场景下的分页功能 + # 1. 所有文章分页 p = Paginator(Article.objects.all(), settings.PAGINATE_BY) self.check_pagination(p, '', '') + # 2. 标签筛选分页 p = Paginator(Article.objects.filter(tags=tag), settings.PAGINATE_BY) self.check_pagination(p, '分类标签归档', tag.slug) + # 3. 作者筛选分页 p = Paginator( - Article.objects.filter( - author__username='liangliangyy'), settings.PAGINATE_BY) + Article.objects.filter(author__username='liangliangyy'), + settings.PAGINATE_BY + ) self.check_pagination(p, '作者文章归档', 'liangliangyy') + # 4. 分类筛选分页 p = Paginator(Article.objects.filter(category=category), settings.PAGINATE_BY) self.check_pagination(p, '分类目录归档', category.slug) + # 测试搜索表单 f = BlogSearchForm() - f.search() - # self.client.login(username='liangliangyy', password='liangliangyy') - from djangoblog.spider_notify import SpiderNotify + f.search() # 调用搜索方法 + + # 测试百度搜索引擎推送 SpiderNotify.baidu_notify([article.get_full_url()]) + # 测试头像相关模板标签 from blog.templatetags.blog_tags import gravatar_url, gravatar - u = gravatar_url('liangliangyy@gmail.com') - u = gravatar('liangliangyy@gmail.com') + u = gravatar_url('liangliangyy@gmail.com') # 获取头像URL + u = gravatar('liangliangyy@gmail.com') # 生成头像HTML + # 测试友情链接 link = Links( sequence=1, name="lylinux", - link='https://wwww.lylinux.net') + link='https://wwww.lylinux.net' + ) link.save() - response = self.client.get('/links.html') + response = self.client.get('/links.html') # 访问友情链接页 self.assertEqual(response.status_code, 200) + # 测试RSS订阅 response = self.client.get('/feed/') self.assertEqual(response.status_code, 200) + # 测试站点地图 response = self.client.get('/sitemap.xml') self.assertEqual(response.status_code, 200) + # 测试admin后台操作(删除文章、访问日志) self.client.get("/admin/blog/article/1/delete/") self.client.get('/admin/servermanager/emailsendlog/') self.client.get('/admin/admin/logentry/') self.client.get('/admin/admin/logentry/1/change/') def check_pagination(self, p, type, value): + """ + 测试分页功能的辅助方法 + 验证分页控件生成的URL是否可正常访问 + """ + # 遍历所有分页页面 for page in range(1, p.num_pages + 1): + # 获取分页信息(通过模板标签) s = load_pagination_info(p.page(page), type, value) - self.assertIsNotNone(s) + self.assertIsNotNone(s) # 验证分页信息生成正常 + + # 测试上一页链接 if s['previous_url']: response = self.client.get(s['previous_url']) self.assertEqual(response.status_code, 200) + + # 测试下一页链接 if s['next_url']: response = self.client.get(s['next_url']) self.assertEqual(response.status_code, 200) def test_image(self): - import requests - rsp = requests.get( - 'https://www.python.org/static/img/python-logo.png') - imagepath = os.path.join(settings.BASE_DIR, 'python.png') + """ + 测试图片上传功能: + - 未授权上传 + - 授权上传 + - 头像保存工具函数 + - 邮件发送工具函数 + """ + # 下载测试图片(Python官方logo) + rsp = requests.get('https://www.python.org/static/img/python-logo.png') + imagepath = os.path.join(settings.BASE_DIR, 'python.png') # 保存路径 with open(imagepath, 'wb') as file: file.write(rsp.content) + + # 测试未授权上传(预期403禁止访问) rsp = self.client.post('/upload') self.assertEqual(rsp.status_code, 403) + + # 生成上传签名(基于SECRET_KEY的双重SHA256加密) sign = get_sha256(get_sha256(settings.SECRET_KEY)) + + # 测试授权上传 with open(imagepath, 'rb') as file: + # 构造上传文件对象 imgfile = SimpleUploadedFile( - 'python.png', file.read(), content_type='image/jpg') + 'python.png', file.read(), content_type='image/jpg' + ) form_data = {'python.png': imgfile} + # 带签名上传 rsp = self.client.post( - '/upload?sign=' + sign, form_data, follow=True) - self.assertEqual(rsp.status_code, 200) + f'/upload?sign={sign}', form_data, follow=True + ) + self.assertEqual(rsp.status_code, 200) # 验证上传成功 + + # 清理测试文件 os.remove(imagepath) + + # 测试用户头像保存和邮件发送工具函数 from djangoblog.utils import save_user_avatar, send_email - send_email(['qq@qq.com'], 'testTitle', 'testContent') - save_user_avatar( - 'https://www.python.org/static/img/python-logo.png') + send_email(['qq@qq.com'], 'testTitle', 'testContent') # 测试发送邮件 + save_user_avatar('https://www.python.org/static/img/python-logo.png') # 测试保存头像 def test_errorpage(self): - rsp = self.client.get('/eee') - self.assertEqual(rsp.status_code, 404) + """测试错误页面(404页面)""" + rsp = self.client.get('/eee') # 访问不存在的URL + self.assertEqual(rsp.status_code, 404) # 验证返回404 def test_commands(self): + """ + 测试Django自定义命令: + - 索引构建、缓存清理、数据同步等 + """ + # 创建测试用户 user = BlogUser.objects.get_or_create( email="liangliangyy@gmail.com", username="liangliangyy")[0] @@ -195,23 +288,26 @@ class ArticleTest(TestCase): user.is_superuser = True user.save() + # 创建OAuth配置 c = OAuthConfig() - c.type = 'qq' + c.type = 'qq' # QQ登录 c.appkey = 'appkey' c.appsecret = 'appsecret' c.save() + # 创建关联用户的OAuth账号 u = OAuthUser() u.type = 'qq' u.openid = 'openid' - u.user = user - u.picture = static("/blog/img/avatar.png") + u.user = user # 关联本地用户 + u.picture = static("/blog/img/avatar.png") # 头像 u.metadata = ''' { "figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30" -}''' +}''' # 第三方平台返回的元数据 u.save() + # 创建未关联本地用户的OAuth账号 u = OAuthUser() u.type = 'qq' u.openid = 'openid1' @@ -222,11 +318,14 @@ class ArticleTest(TestCase): }''' u.save() + # 测试Elasticsearch索引构建命令 from blog.documents import ELASTICSEARCH_ENABLED if ELASTICSEARCH_ENABLED: call_command("build_index") - call_command("ping_baidu", "all") - call_command("create_testdata") - call_command("clear_cache") - call_command("sync_user_avatar") - call_command("build_search_words") + + # 测试其他自定义命令 + call_command("ping_baidu", "all") # 百度链接推送 + call_command("create_testdata") # 创建测试数据 + call_command("clear_cache") # 清理缓存 + call_command("sync_user_avatar") # 同步用户头像 + call_command("build_search_words") # 构建搜索关键词 \ No newline at end of file