| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- from __future__ import annotations
- import json
- import re
- from pathlib import Path
- ROOT = Path(__file__).resolve().parents[1]
- UAT_CASES = ROOT / "docs/acceptance/WP14_UAT_CASES.json"
- UAT_REPORT = ROOT / "docs/acceptance/WP14_UAT_PLAN_AND_REPORT.md"
- DEFECT_REGISTER = ROOT / "docs/acceptance/WP14_DEFECT_REGISTER.md"
- USER_GUIDE = ROOT / "docs/guides/DATAOPS_PHASE1_USER_OPERATION_GUIDE.md"
- OPERATIONS_HANDOVER = ROOT / "docs/runbooks/DATAOPS_PHASE1_OPERATIONS_HANDOVER.md"
- PHASE2_BACKLOG = ROOT / "docs/roadmap/DATAOPS_PHASE2_BACKLOG.md"
- EVIDENCE = ROOT / "docs/validation/WP14_UAT_HANDOVER_EVIDENCE.md"
- REQUEST_CLIENT = ROOT / "frontend/src/utils/request.js"
- DEVELOPMENT_CENTER = (
- ROOT / "frontend/src/views/dataGovernance/development/index.vue"
- )
- DELIVERABLES = (
- UAT_CASES,
- UAT_REPORT,
- DEFECT_REGISTER,
- USER_GUIDE,
- OPERATIONS_HANDOVER,
- PHASE2_BACKLOG,
- EVIDENCE,
- )
- def _read(path: Path) -> str:
- return path.read_text(encoding="utf-8")
- def _cases() -> list[dict]:
- payload = json.loads(_read(UAT_CASES))
- assert payload["work_package"] == "WP-14"
- assert payload["schema_version"] == "1.0"
- return payload["cases"]
- def test_wp14_deliverables_exist() -> None:
- missing = [str(path.relative_to(ROOT)) for path in DELIVERABLES if not path.is_file()]
- assert not missing, f"WP14 交付物缺失: {missing}"
- def test_wp14_uat_cases_cover_roles_modules_and_acceptance_boundaries() -> None:
- cases = _cases()
- assert len(cases) >= 16
- required_fields = {
- "id",
- "module_ids",
- "title",
- "actor",
- "acceptance_level",
- "preconditions",
- "steps",
- "expected",
- "evidence",
- "result",
- "notes",
- }
- for case in cases:
- assert required_fields <= case.keys(), case.get("id")
- assert case["id"].startswith("WP14-UAT-")
- assert case["actor"] in {"admin", "editor", "viewer", "enterprise_acceptance"}
- assert case["acceptance_level"] in {"LOCAL_ENGINEERING", "ENTERPRISE_FORMAL"}
- assert case["result"] in {"PASS_LOCAL", "FAIL", "BLOCKED_EXTERNAL", "NOT_RUN"}
- assert case["module_ids"]
- assert case["preconditions"]
- assert len(case["steps"]) >= 2
- assert case["expected"]
- assert case["evidence"]
- if case["acceptance_level"] == "ENTERPRISE_FORMAL":
- assert case["result"] != "PASS_LOCAL"
- covered_modules = {module for case in cases for module in case["module_ids"]}
- assert {f"WP-{number:02d}" for number in range(2, 14)} <= covered_modules
- assert {"admin", "editor", "viewer"} <= {case["actor"] for case in cases}
- assert any(case["acceptance_level"] == "ENTERPRISE_FORMAL" for case in cases)
- assert any(case["result"] == "BLOCKED_EXTERNAL" for case in cases)
- def test_wp14_docs_state_real_uat_boundary_and_have_no_placeholders() -> None:
- report = _read(UAT_REPORT)
- assert "本地工程预验收" in report
- assert "企业正式验收" in report
- assert "不能替代企业真实数据 UAT" in report
- assert "P0" in report
- assert "签字" in report
- for path in DELIVERABLES[1:]:
- content = _read(path)
- assert not re.search(r"\b(?:TBD|TODO)\b|\{\{[^}]+\}\}", content), path.name
- def test_wp14_defect_register_is_actionable() -> None:
- register = _read(DEFECT_REGISTER)
- for field in ("缺陷编号", "严重度", "状态", "复现与证据", "处置决定"):
- assert field in register
- for severity in ("P0", "P1", "P2", "P3"):
- assert severity in register
- assert "未发现" in register or "已关闭" in register
- def test_wp14_user_and_operations_guides_cover_handover_tasks() -> None:
- user_guide = _read(USER_GUIDE)
- for role in ("管理员", "编辑者", "查看者"):
- assert role in user_guide
- for task in ("设备资产", "实体匹配", "质量问题", "根因", "知识问答", "治理指标"):
- assert task in user_guide
- operations = _read(OPERATIONS_HANDOVER)
- for topic in ("每日巡检", "每周巡检", "备份", "恢复", "回滚", "升级", "异常升级", "责任"):
- assert topic in operations
- assert "培训" in operations
- assert "移交清单" in operations
- def test_wp14_phase2_backlog_preserves_scope_and_sso_gate() -> None:
- backlog = _read(PHASE2_BACKLOG)
- for field in ("待办编号", "来源模块", "优先级", "启动条件", "验收标准", "依赖", "目标阶段"):
- assert field in backlog
- for scope in (
- "主动元数据",
- "通用术语",
- "通用质量运营",
- "平台可观测",
- "统一责任",
- "统一任务",
- "数据产品治理",
- "Agent 治理",
- "安全底座",
- "产品工程",
- ):
- assert scope in backlog
- assert "单点登录" in backlog
- assert "第三阶段" in backlog
- assert "IdP" in backlog
- def test_wp14_evidence_links_results_to_commands_and_pages() -> None:
- evidence = _read(EVIDENCE)
- for section in ("文档契约", "角色与权限", "业务场景", "缺陷结论", "外部门禁"):
- assert section in evidence
- assert "tests/test_wp14_delivery_contract.py" in evidence
- assert "PASS_LOCAL" in evidence
- assert "BLOCKED_EXTERNAL" in evidence
- def test_frontend_accepts_standard_success_envelopes_across_http_2xx() -> None:
- request_client = _read(REQUEST_CLIENT)
- assert "res.code < 200 || res.code >= 300" in request_client
- assert "res.code !== 200" not in request_client
- def test_viewer_development_center_hides_write_only_entries_and_explains_mode() -> None:
- development_center = _read(DEVELOPMENT_CENTER)
- assert 'v-for="entry in visibleEntries"' in development_center
- assert "writeOnly: true" in development_center
- assert "isViewerOnly" in development_center
- assert "当前为 viewer 只读模式" in development_center
|