247 行
9.5 KiB
Python
247 行
9.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
新闻资讯与技术文章改版及丰富度测试 (TDD 模式)
|
|
验证文章独立页、移动端模板、首页联动、数据库种子文件及去AI味道规范
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import unittest
|
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
|
|
def _read_text(path):
|
|
with open(path, encoding="utf-8") as stream:
|
|
return stream.read()
|
|
|
|
|
|
class TestJournalismAndArticles(unittest.TestCase):
|
|
def setUp(self):
|
|
self.pc_list_path = os.path.join(
|
|
BASE_DIR,
|
|
"addons",
|
|
"official",
|
|
"view",
|
|
"web",
|
|
"official_journalism",
|
|
"list.html",
|
|
)
|
|
self.pc_details_path = os.path.join(
|
|
BASE_DIR,
|
|
"addons",
|
|
"official",
|
|
"view",
|
|
"web",
|
|
"official_journalism",
|
|
"details.html",
|
|
)
|
|
self.mobile_list_path = os.path.join(
|
|
BASE_DIR,
|
|
"addons",
|
|
"official",
|
|
"view",
|
|
"web",
|
|
"official_journalism",
|
|
"list_e.html",
|
|
)
|
|
self.mobile_details_path = os.path.join(
|
|
BASE_DIR,
|
|
"addons",
|
|
"official",
|
|
"view",
|
|
"web",
|
|
"official_journalism",
|
|
"details_e.html",
|
|
)
|
|
self.home_index_path = os.path.join(
|
|
BASE_DIR, "addons", "official", "view", "web", "official_home", "index.html"
|
|
)
|
|
self.footer_path = os.path.join(
|
|
BASE_DIR,
|
|
"addons",
|
|
"official",
|
|
"view",
|
|
"web",
|
|
"official_common",
|
|
"pc",
|
|
"footer.html",
|
|
)
|
|
self.css_path = os.path.join(
|
|
BASE_DIR, "public", "assets", "addons", "official", "css", "modern_nhc.css"
|
|
)
|
|
self.seed_sql_path = os.path.join(
|
|
BASE_DIR, "database", "seeds", "journalism_articles.sql"
|
|
)
|
|
|
|
def test_pc_list_template_spec(self):
|
|
"""验证 PC 端文章资讯列表页规范(标题、简介、缩略图专业排版)"""
|
|
self.assertTrue(
|
|
os.path.exists(self.pc_list_path), "PC 文章列表模板 list.html 必须存在"
|
|
)
|
|
content = _read_text(self.pc_list_path)
|
|
self.assertIn("纳海川", content, "必须包含品牌名称【纳海川】")
|
|
self.assertIsNone(
|
|
re.search(r"纳川(?!海)", content), "严禁将品牌错误简写为【纳川】"
|
|
)
|
|
self.assertFalse(
|
|
re.search(
|
|
r"[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\u2600-\u26FF\u2700-\u27BF]",
|
|
content,
|
|
),
|
|
"严禁包含任何 emoji",
|
|
)
|
|
self.assertIn(
|
|
"nhc-article-hero", content, "必须包含现代中式 Hero Banner 容器类"
|
|
)
|
|
self.assertIn(
|
|
"nhc-news-list", content, "必须包含新闻资讯列表容器 nhc-news-list"
|
|
)
|
|
self.assertIn("nhc-news-row", content, "必须包含图文行卡片 nhc-news-row")
|
|
self.assertIn("nhc-news-thumb", content, "必须包含缩略图容器 nhc-news-thumb")
|
|
self.assertIn("nhc-news-title", content, "必须包含文章标题 nhc-news-title")
|
|
self.assertIn("nhc-news-desc", content, "必须包含文章简介 nhc-news-desc")
|
|
self.assertIn("render", content, "必须包含分页渲染组件")
|
|
|
|
def test_pc_details_template_spec(self):
|
|
"""验证 PC 端文章资讯详情页规范"""
|
|
self.assertTrue(
|
|
os.path.exists(self.pc_details_path),
|
|
"PC 文章详情模板 details.html 必须存在",
|
|
)
|
|
content = _read_text(self.pc_details_path)
|
|
self.assertIn("纳海川", content, "必须包含品牌名称【纳海川】")
|
|
self.assertIsNone(
|
|
re.search(r"纳川(?!海)", content), "严禁将品牌错误简写为【纳川】"
|
|
)
|
|
self.assertFalse(
|
|
re.search(
|
|
r"[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\u2600-\u26FF\u2700-\u27BF]",
|
|
content,
|
|
),
|
|
"严禁包含任何 emoji",
|
|
)
|
|
self.assertIn("nhc-article-body", content, "必须包含规范的文章正文排版容器")
|
|
self.assertIn("nhc-breadcrumb", content, "必须包含严谨的面包屑导航")
|
|
self.assertIn(
|
|
"info_previous_next_wrap", content, "必须包含上一篇/下一篇自然导流结构"
|
|
)
|
|
|
|
def test_mobile_templates_spec_and_bugfix(self):
|
|
"""验证移动端模板规范(标题、简介、缩略图专业排版)"""
|
|
self.assertTrue(
|
|
os.path.exists(self.mobile_list_path), "移动端列表模板 list_e.html 必须存在"
|
|
)
|
|
self.assertTrue(
|
|
os.path.exists(self.mobile_details_path),
|
|
"移动端详情模板 details_e.html 必须存在",
|
|
)
|
|
list_content = _read_text(self.mobile_list_path)
|
|
details_content = _read_text(self.mobile_details_path)
|
|
|
|
self.assertIn("nhc-news-thumb", list_content, "移动端列表必须包含缩略图结构")
|
|
self.assertIn("nhc-news-title", list_content, "移动端列表必须包含标题结构")
|
|
self.assertIn("nhc-news-desc", list_content, "移动端列表必须包含简介结构")
|
|
self.assertNotIn(
|
|
"official_video/list",
|
|
details_content,
|
|
"详情页严禁遗留旧 official_video/list 错误路径",
|
|
)
|
|
self.assertFalse(
|
|
re.search(
|
|
r"[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\u2600-\u26FF\u2700-\u27BF]",
|
|
list_content,
|
|
),
|
|
"移动端列表严禁 emoji",
|
|
)
|
|
self.assertFalse(
|
|
re.search(
|
|
r"[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\u2600-\u26FF\u2700-\u27BF]",
|
|
details_content,
|
|
),
|
|
"移动端详情严禁 emoji",
|
|
)
|
|
|
|
def test_css_design_tokens_for_articles(self):
|
|
"""验证 CSS 中已包含文章与资讯专属图文排版样式定义"""
|
|
css = _read_text(self.css_path)
|
|
self.assertIn(".nhc-news-row", css, "CSS 必须定义 .nhc-news-row 图文行卡片样式")
|
|
self.assertIn(".nhc-news-thumb", css, "CSS 必须定义 .nhc-news-thumb 缩略图样式")
|
|
self.assertIn(".nhc-news-title", css, "CSS 必须定义 .nhc-news-title 标题样式")
|
|
self.assertIn(".nhc-news-desc", css, "CSS 必须定义 .nhc-news-desc 简介样式")
|
|
self.assertIn(".nhc-article-body", css, "CSS 必须定义 .nhc-article-body 样式")
|
|
|
|
def test_seed_sql_rich_articles(self):
|
|
"""验证数据库种子包含不少于 38 篇扎实深度专业文章"""
|
|
self.assertTrue(
|
|
os.path.exists(self.seed_sql_path),
|
|
"数据库种子文件 journalism_articles.sql 必须存在",
|
|
)
|
|
sql = _read_text(self.seed_sql_path)
|
|
|
|
# 验证至少 38 篇优质文章插入 (初始 8 篇 + 新增 30 篇)
|
|
insert_count = (
|
|
sql.count("INSERT INTO `fa_official_list_journalism`")
|
|
+ sql.count("INSERT INTO fa_official_list_journalism")
|
|
+ sql.count("REPLACE INTO `fa_official_list_journalism`")
|
|
+ sql.count("REPLACE INTO fa_official_list_journalism")
|
|
)
|
|
self.assertGreaterEqual(
|
|
insert_count,
|
|
38,
|
|
f"必须有至少 38 篇高质量文章 SQL 写入语句 (当前: {insert_count})",
|
|
)
|
|
|
|
# 验证核心业务主题覆盖
|
|
self.assertIn("微服务", sql, "必须覆盖微服务架构深度文章")
|
|
self.assertIn("智能体", sql, "必须覆盖 AI 智能体/大模型与知识库落地文章")
|
|
self.assertTrue(
|
|
"代码" in sql or "软件质量" in sql, "必须覆盖代码规范与交付文章"
|
|
)
|
|
self.assertIn("缓存", sql, "必须覆盖分布式缓存相关深度文章")
|
|
self.assertIn("分库分表", sql, "必须覆盖数据库分库分表相关文章")
|
|
self.assertIn("先进先出", sql, "必须覆盖批次库存先进先出算法相关文章")
|
|
|
|
# 严禁假大空与 AI 味营销词汇
|
|
for bad_word in [
|
|
"赋能千行百业",
|
|
"颠覆式创新",
|
|
"颠覆传统",
|
|
"未来已来",
|
|
"数字化新纪元",
|
|
"技术委员会",
|
|
"研发委员会",
|
|
"原创技术资产",
|
|
"工程受控说明",
|
|
]:
|
|
self.assertNotIn(bad_word, sql, f"文章种子严禁包含 AI 味空话:{bad_word}")
|
|
|
|
def test_home_and_footer_linkage(self):
|
|
"""验证首页与页脚自然联动技术洞察板块"""
|
|
home = _read_text(self.home_index_path)
|
|
footer = _read_text(self.footer_path)
|
|
|
|
# 首页必须包含技术与实践/动态资讯展示区块
|
|
has_news_section = (
|
|
"nhc-insights-section" in home
|
|
or 'id="insights"' in home
|
|
or "技术洞察" in home
|
|
or "技术与实践" in home
|
|
or "研发动态" in home
|
|
or "研发记录" in home
|
|
or "official_journalism" in home
|
|
)
|
|
self.assertTrue(has_news_section, "首页必须包含技术洞察与研发动态板块")
|
|
|
|
# 页脚必须有技术资讯入口
|
|
has_insights_link = (
|
|
"official_journalism" in footer
|
|
or "技术洞察" in footer
|
|
or "新闻资讯" in footer
|
|
)
|
|
self.assertTrue(has_insights_link, "页脚必须包含技术洞察/新闻资讯链接")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|