geo/backend/tests/test_services/test_topic_templates.py

353 lines
12 KiB
Python

"""母题库模块TDD测试
测试策略:
- 测试母题模板数据结构
- 测试Prompt渲染逻辑
- 不使用Mock进行业务逻辑测试
"""
import pytest
from app.services.content.topic_templates import (
TopicTemplate,
TOPIC_TEMPLATES,
get_topic_template,
list_topic_templates,
render_topic_prompt,
)
# ============================================================================
# 母题模板测试
# ============================================================================
class TestTopicTemplate:
"""母题模板数据结构测试"""
def test_topic_template_attributes(self):
"""测试母题模板属性"""
template = TOPIC_TEMPLATES["product_comparison"]
assert template.id == "product_comparison"
assert template.name == "产品对比"
assert template.icon == "⚖️"
assert len(template.prompt_template) > 0
assert len(template.seo_tips) > 0
assert len(template.recommended_platforms) > 0
assert template.word_count_range[0] < template.word_count_range[1]
def test_topic_template_required_params(self):
"""测试母题必填参数"""
template = TOPIC_TEMPLATES["product_comparison"]
assert "brand_name" in template.required_params
assert "competitor_name" in template.required_params
assert "comparison_dimensions" in template.required_params
assert "keywords" in template.required_params
def test_topic_template_optional_params(self):
"""测试母题可选参数"""
template = TOPIC_TEMPLATES["product_comparison"]
assert "content_style" in template.optional_params
assert "word_count" in template.optional_params
class TestAllTopicTemplates:
"""所有母题模板测试"""
def test_all_templates_have_valid_structure(self):
"""测试所有模板具有有效结构"""
for topic_id, template in TOPIC_TEMPLATES.items():
assert template.id == topic_id
assert template.name
assert template.description
assert template.icon
assert template.prompt_template
assert len(template.seo_tips) > 0
assert len(template.recommended_platforms) > 0
assert template.word_count_range[0] > 0
assert template.word_count_range[1] > template.word_count_range[0]
assert len(template.required_params) > 0
def test_all_templates_have_prompt_placeholders(self):
"""测试所有模板包含Prompt占位符"""
for topic_id, template in TOPIC_TEMPLATES.items():
prompt = template.prompt_template
for param in template.required_params:
assert f"{{{param}}}" in prompt, f"Template {topic_id} missing placeholder {{{param}}}"
def test_all_templates_referenced_in_prompt(self):
"""测试所有参数都在Prompt中使用"""
for topic_id, template in TOPIC_TEMPLATES.items():
prompt = template.prompt_template
all_params = template.required_params + template.optional_params
for param in all_params:
if "{" + param + "}" in prompt:
# 如果占位符存在,它应该被正确使用
pass
# ============================================================================
# 母题模板列表测试
# ============================================================================
class TestTopicTemplateFunctions:
"""母题模板函数测试"""
def test_get_existing_template(self):
"""测试获取已存在的模板"""
template = get_topic_template("product_comparison")
assert template is not None
assert template.id == "product_comparison"
def test_get_nonexistent_template(self):
"""测试获取不存在的模板"""
template = get_topic_template("nonexistent")
assert template is None
def test_list_topic_templates(self):
"""测试列出所有模板"""
templates = list_topic_templates()
assert len(templates) == 8
assert all(isinstance(t, TopicTemplate) for t in templates)
def test_list_templates_contains_all_ids(self):
"""测试列出所有模板ID"""
templates = list_topic_templates()
template_ids = [t.id for t in templates]
for topic_id in TOPIC_TEMPLATES.keys():
assert topic_id in template_ids
# ============================================================================
# Prompt渲染测试
# ============================================================================
class TestRenderTopicPrompt:
"""Prompt渲染测试"""
def test_render_product_comparison_prompt(self):
"""测试渲染产品对比Prompt"""
params = {
"brand_name": "华为",
"competitor_name": "小米",
"comparison_dimensions": "性能、价格、外观",
"keywords": "手机,5G,性价比",
"content_style": "专业",
"word_count": 2000,
}
prompt = render_topic_prompt("product_comparison", params)
assert "华为" in prompt
assert "小米" in prompt
assert "性能、价格、外观" in prompt
assert "手机,5G,性价比" in prompt
assert "2000" in prompt
def test_render_how_to_guide_prompt(self):
"""测试渲染使用指南Prompt"""
params = {
"product_name": "iPhone 15",
"core_features": "拍照、续航、系统",
"target_audience": "普通用户",
"keywords": "iPhone,苹果,手机",
}
prompt = render_topic_prompt("how_to_guide", params)
assert "iPhone 15" in prompt
assert "拍照、续航、系统" in prompt
def test_render_industry_trends_prompt(self):
"""测试渲染行业趋势Prompt"""
params = {
"industry_name": "新能源汽车",
"brand_perspective": "技术创新",
"analysis_dimensions": "技术、市场、政策",
"keywords": "电动车,电池,自动驾驶",
}
prompt = render_topic_prompt("industry_trends", params)
assert "新能源汽车" in prompt
assert "技术创新" in prompt
def test_render_with_default_params(self):
"""测试使用默认参数渲染"""
params = {
"brand_name": "测试品牌",
"competitor_name": "竞品",
"comparison_dimensions": "功能",
"keywords": "关键词",
}
prompt = render_topic_prompt("product_comparison", params)
# content_style和word_count应有默认值
assert "content_style" not in params or "专业" in prompt or "专业" in params.get("content_style", "")
def test_render_nonexistent_template_raises_error(self):
"""测试渲染不存在的模板抛出错误"""
with pytest.raises(ValueError, match="Unknown topic"):
render_topic_prompt("nonexistent_topic", {})
# ============================================================================
# 各母题模板内容测试
# ============================================================================
class TestProductComparison:
"""产品对比母题测试"""
def test_template_has_comparison_structure(self):
"""测试模板包含对比结构"""
template = TOPIC_TEMPLATES["product_comparison"]
prompt = template.prompt_template
# 验证包含对比维度
assert "对比" in prompt
# 验证包含SEO提示
assert any("对比" in tip for tip in template.seo_tips)
class TestHowToGuide:
"""使用指南母题测试"""
def test_template_has_step_structure(self):
"""测试模板包含步骤结构"""
template = TOPIC_TEMPLATES["how_to_guide"]
prompt = template.prompt_template
# 验证包含步骤相关关键词
assert "步骤" in prompt or "教程" in prompt or "使用" in prompt
class TestIndustryTrends:
"""行业趋势母题测试"""
def test_template_has_trend_analysis(self):
"""测试模板包含趋势分析"""
template = TOPIC_TEMPLATES["industry_trends"]
prompt = template.prompt_template
# 验证包含趋势相关关键词
assert "趋势" in prompt or "分析" in prompt or "预测" in prompt
class TestExpertOpinion:
"""专家观点母题测试"""
def test_template_has_expert_identity(self):
"""测试模板包含专家身份"""
template = TOPIC_TEMPLATES["expert_opinion"]
assert "expert_identity" in template.required_params
assert "core_opinion" in template.required_params
class TestCaseStudy:
"""案例研究母题测试"""
def test_template_has_case_structure(self):
"""测试模板包含案例结构"""
template = TOPIC_TEMPLATES["case_study"]
prompt = template.prompt_template
assert "case_name" in template.required_params
assert "company_background" in template.required_params
class TestDataReport:
"""数据报告母题测试"""
def test_template_has_data_structure(self):
"""测试模板包含数据报告结构"""
template = TOPIC_TEMPLATES["data_report"]
assert "report_topic" in template.required_params
assert "data_scope" in template.required_params
assert "core_findings" in template.required_params
# 数据报告字数范围应较大
assert template.word_count_range[0] >= 2000
class TestFAQ:
"""问题解答母题测试"""
def test_template_has_faq_structure(self):
"""测试模板包含FAQ结构"""
template = TOPIC_TEMPLATES["faq"]
prompt = template.prompt_template
assert "questions" in template.required_params
# FAQ字数范围应较小
assert template.word_count_range[1] <= 2500
class TestReview:
"""评测报告母题测试"""
def test_template_has_review_structure(self):
"""测试模板包含评测结构"""
template = TOPIC_TEMPLATES["review"]
prompt = template.prompt_template
assert "product_name" in template.required_params
assert "review_dimensions" in template.required_params
# 评测应包含优缺点
assert "" in prompt or "" in prompt or "评测" in prompt
# ============================================================================
# SEO提示测试
# ============================================================================
class TestSEOTips:
"""SEO提示测试"""
def test_all_templates_have_seo_tips(self):
"""测试所有模板都有SEO提示"""
for topic_id, template in TOPIC_TEMPLATES.items():
assert len(template.seo_tips) > 0, f"Template {topic_id} missing SEO tips"
def test_seo_tips_are_descriptive(self):
"""测试SEO提示具有描述性"""
for topic_id, template in TOPIC_TEMPLATES.items():
for tip in template.seo_tips:
assert len(tip) > 5, f"Template {topic_id} has too short SEO tip"
# ============================================================================
# 推荐平台测试
# ============================================================================
class TestRecommendedPlatforms:
"""推荐平台测试"""
def test_all_templates_have_recommended_platforms(self):
"""测试所有模板都有推荐平台"""
for topic_id, template in TOPIC_TEMPLATES.items():
assert len(template.recommended_platforms) > 0, f"Template {topic_id} missing platforms"
def test_platforms_are_valid(self):
"""测试平台名称有效"""
common_platforms = {"知乎", "百家号", "公众号", "小红书", "简书", "微博"}
for topic_id, template in TOPIC_TEMPLATES.items():
for platform in template.recommended_platforms:
# 平台应该在常见平台列表中或是有效的
assert platform, f"Template {topic_id} has empty platform name"