# 赵瑞萍:评论功能测试模块,用于验证评论发布、回复、审核及显示等核心流程 # 基于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)