Files
dev_harness/tests/test_harness_docs.py
T

199 lines
7.9 KiB
Python
Raw Normal View History

from __future__ import annotations
import sys
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "dev_scripts"))
from check_harness import ( # noqa: E402
CORE_DOCUMENT_REQUIREMENTS,
CORE_PAGE_PATHS,
REQUIRED_FILES,
check_claude_code_entry,
check_core_documents,
check_agent_efficiency_rules,
check_task_template,
2026-08-08 09:02:48 +08:00
core_mapping_errors,
missing_sections,
)
from wiki_docs import load_config # noqa: E402
class CoreDocumentTests(unittest.TestCase):
def test_current_core_documents_have_required_sections(self) -> None:
errors: list[str] = []
check_core_documents(errors)
self.assertEqual(errors, [])
def test_missing_sections_reports_each_heading(self) -> None:
missing = missing_sections("# 页面\n## 已有\n", ("## 已有", "## 缺少"))
self.assertEqual(missing, ["## 缺少"])
def test_every_core_document_is_required(self) -> None:
for path in CORE_DOCUMENT_REQUIREMENTS:
self.assertIn(path, REQUIRED_FILES)
def test_every_core_page_has_exact_mapping(self) -> None:
config = load_config()
mappings = {mapping.page: mapping.path for mapping in config.mappings}
for page, path in CORE_PAGE_PATHS.items():
self.assertEqual(mappings.get(page), path)
2026-08-16 19:21:36 +08:00
def test_task_archives_are_not_core_mappings(self) -> None:
config = load_config()
self.assertFalse(
any(mapping.path.startswith("docs/task/") for mapping in config.mappings)
)
2026-08-10 15:01:15 +08:00
def test_existing_project_adoption_guide_is_core_document(self) -> None:
path = "docs/08-existing-project-adoption.md"
self.assertEqual(
CORE_PAGE_PATHS.get("Existing-Project-Adoption-Guide"),
path,
)
self.assertIn(path, CORE_DOCUMENT_REQUIREMENTS)
self.assertIn("## 可复制 Agent 指令", CORE_DOCUMENT_REQUIREMENTS[path])
def test_new_project_setup_requires_baseline_selection(self) -> None:
required = CORE_DOCUMENT_REQUIREMENTS[
"docs/07-new-project-documentation-setup.md"
]
self.assertIn("### 2. 选择建设基线", required)
2026-08-16 19:39:08 +08:00
self.assertIn("#### 判断案例", required)
self.assertIn("### 3. 识别子项目与交付单元", required)
2026-08-08 09:02:48 +08:00
def test_missing_or_wrong_core_mapping_is_reported(self) -> None:
errors = core_mapping_errors({"Home": "docs/wrong.md"})
self.assertTrue(any("Home -> docs/README.md" in error for error in errors))
self.assertTrue(
any("Architecture-and-Code-Map" in error for error in errors)
)
class TaskTemplateTests(unittest.TestCase):
def test_task_template_requires_document_impact(self) -> None:
errors: list[str] = []
check_task_template(errors)
self.assertEqual(errors, [])
2026-08-10 14:25:34 +08:00
def test_task_template_requires_delivery_document_impact(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text(
"## 依赖与并行\n"
"- 前置工单:无 / #编号\n"
"- 是否允许与前置工单并行:是 / 否\n"
"- 原因:\n"
"## 原始需求\n"
"- 来源:用户对话 / Gitea / 其他\n"
"- 提出时间:\n"
"- 关键原话或脱敏摘要:\n"
"## 需求变化记录\n"
"| 日期 | 变化内容 | 原因 | 用户确认 |\n"
"## 文档影响\n"
"- [ ] 不影响长期文档,原因:\n"
"- [ ] 更新架构与代码地图\n"
"- [ ] 更新业务规则与术语\n"
"- [ ] 更新常见修改或故障排查\n",
encoding="utf-8",
)
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 交付文档影响", errors)
self.assertIn(
"单元任务模板缺少:- [ ] 无交付文档影响,原因:",
errors,
)
def test_task_template_requires_subproject_impact(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text("## 基本信息\n", encoding="utf-8")
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 子项目影响", errors)
self.assertIn(
"单元任务模板缺少:- 是否跨子项目:是 / 否",
errors,
)
self.assertIn(
"单元任务模板缺少:- 是否修改共享接口或契约:是 / 否;唯一事实来源:",
errors,
)
2026-08-10 00:30:31 +08:00
def test_task_template_requires_dependency_fields(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text(
"## 文档影响\n"
"- [ ] 不影响长期文档,原因:\n"
"- [ ] 更新架构与代码地图\n"
"- [ ] 更新业务规则与术语\n"
"- [ ] 更新常见修改或故障排查\n",
encoding="utf-8",
)
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 依赖与并行", errors)
self.assertIn("单元任务模板缺少:- 前置工单:无 / #编号", errors)
2026-08-10 11:53:38 +08:00
def test_task_template_requires_requirement_traceability(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text(
"## 依赖与并行\n"
"- 前置工单:无 / #编号\n"
"- 是否允许与前置工单并行:是 / 否\n"
"- 原因:\n"
"## 文档影响\n"
"- [ ] 不影响长期文档,原因:\n"
"- [ ] 更新架构与代码地图\n"
"- [ ] 更新业务规则与术语\n"
"- [ ] 更新常见修改或故障排查\n",
encoding="utf-8",
)
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 原始需求", errors)
self.assertIn("单元任务模板缺少:## 需求变化记录", errors)
class AgentRuleTests(unittest.TestCase):
2026-08-10 01:09:13 +08:00
def test_required_agent_rules_are_present(self) -> None:
errors: list[str] = []
check_agent_efficiency_rules(errors)
self.assertEqual(errors, [])
def test_claude_code_entry_imports_shared_rules(self) -> None:
errors: list[str] = []
check_claude_code_entry(errors)
self.assertEqual(errors, [])
def test_claude_code_entry_requires_exact_import_line(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
(root / "CLAUDE.md").write_text(
"共同规则事实来源\n只记录 Claude Code 特有\n"
"共同规则只修改 `AGENTS.md`\n",
encoding="utf-8",
)
errors: list[str] = []
check_claude_code_entry(errors, root)
self.assertIn("CLAUDE.md 缺少独立的 @AGENTS.md 导入", errors)
if __name__ == "__main__":
unittest.main()