geo/tests/test_platform_rules.py

164 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""平台规则引擎单元测试"""
import pytest
# ---------------------------------------------------------------------------
# PlatformRuleEngine 测试
# ---------------------------------------------------------------------------
class TestPlatformRuleEngine:
@pytest.fixture
def engine(self):
from app.services.distribution.platform_rules import PlatformRuleEngine
return PlatformRuleEngine()
def test_get_platforms_returns_all(self, engine):
"""返回所有 6 个平台"""
platforms = engine.get_platforms()
assert len(platforms) == 6
ids = {p["id"] for p in platforms}
assert ids == {"wechat", "zhihu", "xiaohongshu", "baijiahao", "douyin", "toutiao"}
def test_get_platforms_fields(self, engine):
"""每个平台包含必要字段"""
platforms = engine.get_platforms()
required_fields = {"id", "name", "icon", "max_title_length", "max_content_length",
"min_content_length", "supported_media", "max_images"}
for p in platforms:
assert required_fields.issubset(p.keys())
def test_validate_title_too_long(self, engine):
"""标题超长返回 high severity issue"""
# 微信公众号标题上限 22 字
title = "这个标题非常非常非常非常非常非常非常长超过了微信的限制"
content = "这是正文内容,字数足够满足最低要求。" * 30
result = engine.validate_content(content, title, "wechat")
assert result["is_valid"] is False
issues = result["issues"]
high_issues = [i for i in issues if i["severity"] == "high"]
assert any("标题" in i["message"] for i in high_issues)
def test_validate_content_too_short(self, engine):
"""内容过短返回 medium severity issue"""
title = "正常标题"
content = "短内容" # 远少于 300 字最低要求
result = engine.validate_content(content, title, "wechat")
issues = result["issues"]
assert any("内容长度" in i["message"] for i in issues)
def test_validate_valid_content(self, engine):
"""合规内容 score >= 90"""
title = "合规标题测试" # 长度在 22 字以内
content = "这是符合要求的内容。" * 50 # 足够长度,无违规
result = engine.validate_content(content, title, "wechat")
assert result["score"] >= 90
def test_validate_unknown_platform(self, engine):
"""未知平台返回 is_valid=False"""
result = engine.validate_content("content", "title", "unknown_platform_xyz")
assert result["is_valid"] is False
assert result["score"] == 0
def test_validate_wechat_external_link(self, engine):
"""微信正文包含外部链接返回 high severity issue"""
title = "标题"
content = "正文内容 " * 50 + " 点击 https://example.com/test 查看"
result = engine.validate_content(content, title, "wechat")
issues = result["issues"]
assert any("外部链接" in i["message"] for i in issues)
def test_validate_wechat_consecutive_symbols_in_title(self, engine):
"""微信标题含连续特殊符号返回 medium issue"""
title = "惊喜!!!三连"
content = "正文内容,满足最低字数要求。" * 30
result = engine.validate_content(content, title, "wechat")
issues = result["issues"]
assert any("连续特殊符号" in i["message"] for i in issues)
def test_get_optimization_tips_returns_list(self, engine):
"""get_optimization_tips 返回非空列表"""
tips = engine.get_optimization_tips("wechat")
assert isinstance(tips, list)
assert len(tips) > 0
def test_get_optimization_tips_unknown_platform(self, engine):
"""未知平台返回空列表"""
tips = engine.get_optimization_tips("unknown_xyz")
assert tips == []
# ---------------------------------------------------------------------------
# ContentFormatter 测试
# ---------------------------------------------------------------------------
class TestContentFormatter:
@pytest.fixture
def formatter(self):
from app.services.distribution.formatter import ContentFormatter
return ContentFormatter()
def test_formatter_xiaohongshu_strips_markdown(self, formatter):
"""小红书格式:移除 Markdown 标记"""
md_content = "# 标题\n\n**加粗内容**\n\n[链接文本](http://example.com)"
result = formatter.format_for_platform(md_content, "xiaohongshu")
assert "**" not in result
assert "#" not in result or result.strip().startswith("#") is False
assert "http://example.com" not in result
def test_formatter_wechat_removes_links(self, formatter):
"""微信格式:去除非公众号外链,保留链接文本"""
content = "请访问 [示例网站](https://external-site.com/page) 了解详情"
result = formatter.format_for_platform(content, "wechat")
# 外部链接被移除,但文本保留
assert "https://external-site.com" not in result
assert "示例网站" in result
def test_formatter_wechat_converts_headers(self, formatter):
"""微信格式Markdown 标题转 HTML"""
content = "## 二级标题\n\n正文内容"
result = formatter.format_for_platform(content, "wechat")
assert "<h2>" in result
assert "二级标题" in result
def test_formatter_zhihu_keeps_markdown(self, formatter):
"""知乎格式:保留 Markdown 结构"""
content = "## 知乎标题\n\n**加粗内容**\n\n`代码示例`"
result = formatter.format_for_platform(content, "zhihu")
# 知乎支持 Markdown应保留
assert "**加粗内容**" in result
def test_formatter_default_strips_markdown(self, formatter):
"""默认格式:清理 Markdown 为纯文本"""
content = "# 标题\n\n**加粗**\n\n[链接](http://test.com)"
result = formatter.format_for_platform(content, "unknown_platform")
assert "#" not in result.split("\n")[0] # 标题标记被移除
assert "**" not in result
assert "http://test.com" not in result
def test_formatter_xiaohongshu_tags_moved_to_end(self, formatter):
"""小红书格式:话题标签移到文末"""
content = "正文内容 #话题1 更多内容 #话题2"
result = formatter.format_for_platform(content, "xiaohongshu")
lines = result.strip().split("\n")
last_line = lines[-1]
# 最后一行包含标签
assert "#话题1" in last_line or "#话题2" in last_line
def test_formatter_wechat_bold_to_strong(self, formatter):
"""微信格式:**加粗** 转为 <strong>"""
content = "这是**重要内容**需要加粗"
result = formatter.format_for_platform(content, "wechat")
assert "<strong>重要内容</strong>" in result