Files
2026Technology-Competition/tests/test_zh_template.py
T
lhl d01e1b720f feat(writer): 输出语言一致性保障 + 用户可选输出语言
- 步骤0: 新增中文镜像模板 scripts/make_zh_template.py 与 samples/概要设计书模板_中文.docx(7章锚点原样保留)
- 步骤1: config.WriterConfig.output_language→Settings.writer;GenerationContext.output_language + to_vars.language_instruction(zh/ja/auto);writer_agent【语言约束】改引变量;context_builder/orchestrator/run_trial 透传 --output-language
- 步骤A: 新建 src/genesis/writer/language.py(detect_script/resolve_expected_language/find_language_violations);WriterAgent.generate_chapter 按期望语言强制、违规重试、耗尽硬失败;max_retries 默认 1→2
- 步骤B: _format_impact 影响调查标签按 output_language 本地化(zh 新建/变更/删除/警告)
- 步骤C: eval scorer 第 11 维度 language_consistency(不可验证=满分,不拉低总分);ChapterArtifact.expected_language;QAValidator.validate_doc 透传;QALoop.run 透传 output_language
- 测试: test_zh_template/test_language_plumbing/test_writer_language/test_scorer_language/test_language_coverage,并更新 test_phase5_e2e
- 全量 pytest 424 passed / 99.15%(覆盖率门槛 99% 达标)
2026-08-25 23:30:24 +08:00

78 lines
2.6 KiB
Python

"""中文样本模板镜像测试(步骤 0)。
断言 zh 模板与 ja 模板章节结构一致:7 个 H1 章、锚点 id(section:xxx)逐一对应,
且锚点段落文本原样保留(映射/注入器零改动)。
"""
from __future__ import annotations
import shutil
from pathlib import Path
import pytest
from docx import Document
from genesis.parsers.word_template_parser import WordTemplateParser
from genesis.writer.template_mapper import map_template
_SAMPLES = Path(r"D:\00_project\Genesis\samples")
_JA = _SAMPLES / "概要設計書テンプレート.docx"
_ZH = _SAMPLES / "概要设计书模板_中文.docx"
EXPECTED_ANCHORS = [
"introduction", "function_list", "screen_list", "report_list",
"db_design", "if_definition", "batch_list",
]
@pytest.fixture
def zh_template(tmp_path):
"""生成 zh 模板到临时目录并返回路径(不污染 samples/)。"""
from scripts.make_zh_template import build_zh_template
dst = tmp_path / "概要设计书模板_中文.docx"
build_zh_template(str(_JA), str(dst))
return dst
def _parse(path: Path):
return WordTemplateParser().parse(str(path))
def test_zh_template_has_same_seven_chapter_anchors(zh_template):
ja = _parse(_JA)
zh = _parse(zh_template)
ja_ids = [ph for ph in ja.placeholders if ph.startswith("section:")]
zh_ids = [ph for ph in zh.placeholders if ph.startswith("section:")]
assert sorted(zh_ids) == sorted(ja_ids)
assert zh_ids == [f"section:{a}" for a in EXPECTED_ANCHORS]
def test_zh_template_anchor_paragraphs_unchanged(zh_template):
"""锚点段落文本在 zh 模板中必须与 ja 完全一致(映射/注入器依赖它)。"""
ja_doc = Document(str(_JA))
zh_doc = Document(str(zh_template))
ja_anchors = [p.text for p in ja_doc.paragraphs if p.text.startswith("{{section:")]
zh_anchors = [p.text for p in zh_doc.paragraphs if p.text.startswith("{{section:")]
assert zh_anchors == ja_anchors
def test_zh_template_headings_translated(zh_template):
zh_doc = Document(str(zh_template))
texts = {p.text for p in zh_doc.paragraphs if p.style.name.startswith("Heading")}
assert "1. 前言" in texts
assert "2. 功能一览" in texts
assert "5. DB设计" in texts
assert "7. 批处理一览" in texts
def test_zh_template_maps_to_same_seven_chapters(zh_template):
"""template_mapper 对 zh 模板产出 7 个章节,锚点与 ja 对应。"""
pt = _parse(zh_template)
specs = map_template(pt)
assert len(specs) == 7
assert [s.section_placeholder for s in specs] == [
f"section:{a}" for a in EXPECTED_ANCHORS
]