|
|
# 赵瑞萍:评论功能测试模块,用于验证评论发布、回复、审核及显示等核心流程
|
|
|
# 基于Django TransactionTestCase,支持数据库事务操作,覆盖评论功能的关键场景测试
|
|
|
|
|
|
# 赵瑞萍:导入Django测试核心工具,提供请求模拟、URL解析等能力
|
|
|
from django.test import Client, RequestFactory, TransactionTestCase
|
|
|
from django.urls import reverse # 用于反向解析视图URL,避免硬编码
|
|
|
|
|
|
# 赵瑞萍:导入测试所需的模型和工具,覆盖用户、文章、评论等关联数据
|
|
|
from accounts.models import BlogUser # 自定义用户模型,用于创建测试用户
|
|
|
from blog.models import Category, Article, BlogSettings # 博客分类、文章、设置模型
|
|
|
from comments.models import Comment # 评论模型,测试核心对象
|
|
|
from comments.templatetags.comments_tags import * # 评论模板标签,用于测试评论树解析
|
|
|
from djangoblog.utils import get_max_articleid_commentid # 工具函数,辅助测试数据处理
|
|
|
|
|
|
|
|
|
class CommentsTest(TransactionTestCase):
|
|
|
"""
|
|
|
赵瑞萍:评论功能测试类,继承TransactionTestCase支持事务回滚,确保测试独立性
|
|
|
覆盖场景:评论发布、回复评论、评论审核状态、评论列表显示等核心功能
|
|
|
"""
|
|
|
|
|
|
def setUp(self):
|
|
|
"""
|
|
|
赵瑞萍:测试前置初始化方法,每个测试函数执行前自动调用
|
|
|
初始化测试客户端、请求工厂、测试数据(用户、博客设置),为测试提供基础环境
|
|
|
"""
|
|
|
# 赵瑞萍:创建测试客户端,用于模拟用户发起HTTP请求(如提交评论)
|
|
|
self.client = Client()
|
|
|
# 赵瑞萍:创建请求工厂,用于构造自定义请求对象(灵活模拟请求场景)
|
|
|
self.factory = RequestFactory()
|
|
|
|
|
|
# 赵瑞萍:配置博客评论设置,开启"评论需要审核"功能(模拟真实业务场景)
|
|
|
value = BlogSettings()
|
|
|
value.comment_need_review = True # 评论需审核后才显示
|
|
|
value.save() # 保存设置到数据库
|
|
|
|
|
|
# 赵瑞萍:创建超级用户,用于测试登录状态下的评论发布权限
|
|
|
self.user = BlogUser.objects.create_superuser(
|
|
|
email="liangliangyy1@gmail.com",
|
|
|
username="liangliangyy1",
|
|
|
password="liangliangyy1"
|
|
|
)
|
|
|
|
|
|
def update_article_comment_status(self, article):
|
|
|
"""
|
|
|
赵瑞萍:测试辅助方法,用于批量更新文章评论为"启用"状态(模拟审核通过)
|
|
|
参数:article - 目标文章对象,需启用其下所有评论
|
|
|
"""
|
|
|
# 赵瑞萍:获取该文章关联的所有评论查询集
|
|
|
comments = article.comment_set.all()
|
|
|
# 赵瑞萍:遍历评论,将is_enable设为True(审核通过)并保存
|
|
|
for comment in comments:
|
|
|
comment.is_enable = True
|
|
|
comment.save()
|
|
|
|
|
|
def test_validate_comment(self):
|
|
|
"""
|
|
|
赵瑞萍:核心测试方法,验证评论发布、回复、审核显示等完整流程
|
|
|
包含:登录验证、文章创建、普通评论发布、嵌套回复、Markdown内容测试
|
|
|
"""
|
|
|
# 赵瑞萍:模拟用户登录,获取评论发布权限(需登录才能评论)
|
|
|
self.client.login(username='liangliangyy1', password='liangliangyy1')
|
|
|
|
|
|
# 赵瑞萍:创建测试分类(文章必须关联分类,满足模型约束)
|
|
|
category = Category()
|
|
|
category.name = "categoryccc"
|
|
|
category.save()
|
|
|
|
|
|
# 赵瑞萍:创建测试文章(评论需关联文章,为评论提供目标对象)
|
|
|
article = Article()
|
|
|
article.title = "nicetitleccc" # 文章标题
|
|
|
article.body = "nicecontentccc" # 文章内容
|
|
|
article.author = self.user # 关联创建者(超级用户)
|
|
|
article.category = category # 关联分类
|
|
|
article.type = 'a' # 假设'a'为普通文章类型(符合项目定义)
|
|
|
article.status = 'p' # 假设'p'为已发布状态(只有已发布文章可评论)
|
|
|
article.save()
|
|
|
|
|
|
# 赵瑞萍:反向解析评论提交视图的URL,传入文章ID参数
|
|
|
comment_url = reverse(
|
|
|
'comments:postcomment', kwargs={'article_id': article.id}
|
|
|
)
|
|
|
|
|
|
# 赵瑞萍:测试场景1 - 发布第一条普通评论
|
|
|
response = self.client.post(
|
|
|
comment_url,
|
|
|
{'body': '123ffffffffff'} # 评论内容
|
|
|
)
|
|
|
# 赵瑞萍:验证评论提交后是否重定向(通常跳回文章详情页,状态码302)
|
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
|
|
# 赵瑞萍:从数据库刷新文章对象(获取最新关联的评论数据)
|
|
|
article = Article.objects.get(pk=article.pk)
|
|
|
# 赵瑞萍:未审核的评论is_enable=False,评论列表长度应为0
|
|
|
self.assertEqual(len(article.comment_list()), 0)
|
|
|
# 赵瑞萍:调用辅助方法模拟审核通过,启用评论
|
|
|
self.update_article_comment_status(article)
|
|
|
# 赵瑞萍:审核后评论应显示,列表长度应为1
|
|
|
self.assertEqual(len(article.comment_list()), 1)
|
|
|
|
|
|
# 赵瑞萍:测试场景2 - 发布第二条普通评论(验证多评论存储)
|
|
|
response = self.client.post(
|
|
|
comment_url,
|
|
|
{'body': '123ffffffffff'}
|
|
|
)
|
|
|
self.assertEqual(response.status_code, 302) # 验证重定向
|
|
|
article = Article.objects.get(pk=article.pk)
|
|
|
self.update_article_comment_status(article)
|
|
|
self.assertEqual(len(article.comment_list()), 2) # 验证评论数量增加
|
|
|
|
|
|
# 赵瑞萍:测试场景3 - 回复评论(嵌套回复功能)
|
|
|
# 获取第一条评论的ID,作为父评论ID(建立回复关联)
|
|
|
parent_comment_id = article.comment_list()[0].id
|
|
|
|
|
|
# 赵瑞萍:发布带Markdown格式的回复(测试富文本内容支持)
|
|
|
response = self.client.post(
|
|
|
comment_url,
|
|
|
{
|
|
|
'body': '''
|
|
|
# Title1 (Markdown标题)
|
|
|
|
|
|
```python
|
|
|
import os # Markdown代码块
|
|
|
''',
|
|
|
'parent_comment_id': parent_comment_id # 传入父评论ID,标识为回复
|
|
|
}
|
|
|
)
|
|
|
# 赵瑞萍:验证回复提交是否成功(重定向)
|
|
|
self.assertEqual(response.status_code, 302)
|
|
|
# 赵瑞萍:刷新文章对象并启用所有评论(模拟审核)
|
|
|
article = Article.objects.get(pk=article.pk)
|
|
|
self.update_article_comment_status(article)
|
|
|
# 赵瑞萍:验证总评论数(原有2条+1条回复=3条)
|
|
|
self.assertEqual(len(article.comment_list()), 3)
|
|
|
|
|
|
# 赵瑞萍:测试场景4 - 验证评论树解析(通过模板标签解析嵌套关系)
|
|
|
# 获取所有已启用的评论查询集
|
|
|
comment_list = Comment.objects.filter(is_enable=True)
|
|
|
# 获取第一条评论(父评论)
|
|
|
parent_comment = comment_list.first()
|
|
|
# 调用模板标签函数,解析该父评论的所有子评论
|
|
|
child_comments = parse_commenttree(comment_list, parent_comment)
|
|
|
# 赵瑞萍:验证子评论数量(仅1条回复)
|
|
|
self.assertEqual(len(child_comments), 1)
|
|
|
# 赵瑞萍:验证子评论的父评论ID是否正确匹配
|
|
|
self.assertEqual(child_comments[0].parent_comment.id, parent_comment.id) |