Files
xst 8c61209dd4 test(物流公司管理需求): 需求文档与 QE Fleet 全流程设计产物入库
- 需求 v1.1 + 2026-09-29 需求方确认的 Q7~Q19 决议(含 BR-07/BR-09/6.7/6.9 矛盾表述修订)
- 测试点 159 个、测试用例 164 条(P0 55/P1 81/P2 23/P3 5),需求→测试点→用例三级追溯覆盖率 100%
- 质量裁决 PASS(首轮 PASS_WITH_FIX,13 项待确认确认后复裁决升级);评审原始 2 阻断项+9 建议项+3 优化项已全部修复
- 确认单:与 4 个历史需求均为并行关系、0 冲突、0 回写
- 附导出 v1/v2 版本快照、Playwright/Appium 脚本骨架、覆盖率审计脚本与指标、评审修复脚本
2026-09-29 10:03:35 +08:00

164 lines
12 KiB
Python
Raw Permalink 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.
# -*- coding: utf-8 -*-
"""按《评审报告》修复用例文件:2 个阻断项 + 9 条建议项 + 1 处笔误。
每条替换均断言命中次数,任一不命中即抛错并中止,保证不误伤其它行。
"""
from __future__ import annotations
import re
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.stdout.reconfigure(encoding="utf-8")
CASES = REPO / "output" / "test_cases" / "物流公司管理需求_测试用例.md"
# ---------- GB 32100 校验位 ----------
CHARSET = "0123456789ABCDEFGHJKLMNPQRTUWXY"
WEIGHTS = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28]
def uscc_check_char(body17: str) -> str:
assert len(body17) == 17, body17
total = sum(CHARSET.index(ch) * WEIGHTS[i] for i, ch in enumerate(body17))
rem = 31 - (total % 31)
return CHARSET[0 if rem == 31 else rem]
def verify_uscc(uscc: str) -> bool:
return len(uscc) == 18 and uscc_check_char(uscc[:17]) == uscc[17]
# 自检:对已知有效样本验证算法
assert verify_uscc("91530102MA6N4K7X52"), "算法自检失败(1)"
assert verify_uscc("91530103MA6P8Q2D7F"), "算法自检失败(2)"
NEW_BODY = "91530102MA6BA5C31"
NEW_USCC = NEW_BODY + uscc_check_char(NEW_BODY)
assert verify_uscc(NEW_USCC), "新样本自检失败"
print(f"061 重建样本新信用代码: {NEW_USCC}")
# ---------- 修复项:(用例编号, 列定位说明, 旧文本, 新文本) ----------
FIXES: list[tuple[str, str, str, str]] = [
# B-001
("PLT_BSC_LC_028", "预期结果",
"3. 纯空格提交按未填处理被阻断(trim 后为空口径)",
"3. 纯空格提交的实际行为记录(按空拦截 或 通过),与测试数据 §10 补充-6 口径比对后回归(评审确认前不得静默按单一口径判定)"),
("PLT_BSC_LC_028", "备注",
"对应TP-B-010;REQ-007 |",
"对应TP-B-010;REQ-007;[待确认] 纯空格/空白字符在必填字段中是否按空处理(见测试数据 §10 补充-6,与 PLT_BSC_LC_022 同口径) |"),
("PLT_BSC_LC_032", "预期结果",
"3. 纯空格按未填处理被阻断",
"3. 纯空格提交的实际行为记录(按空拦截 或 通过),与 PLT_BSC_LC_022 口径比对后回归"),
("PLT_BSC_LC_032", "备注",
"对应TP-B-014;REQ-007(漏测清单 §1 超长字符) |",
"对应TP-B-014;REQ-007(漏测清单 §1 超长字符);[待确认] 纯空格/空白字符是否按空处理(见测试数据 §10 补充-6) |"),
# B-002
("PLT_BSC_LC_073", "测试步骤",
"4. 核对上传后文件名展示",
"4. 核对上传后文件名展示<br>5. 上传大写扩展名样本(合同.PDF、合同.Jpg,AT-03)并记录实际口径"),
("PLT_BSC_LC_073", "预期结果",
"4. 无扩展名文件(\"合同附件\")被拒绝;拒绝后不产生上传残留",
"4. 无扩展名文件(\"合同附件\")被拒绝;拒绝后不产生上传残留<br>5. 大写扩展名的实际处理行为记录(大小写不敏感放行 或 仅接受小写并提示),与评审结论对齐后回归,不得静默按单一口径断言"),
("PLT_BSC_LC_073", "备注",
"对应TP-E-012;REQ-019/BR-03 |",
"对应TP-E-012;REQ-019/BR-03;[待确认] 合同附件扩展名大小写口径(.PDF/.Jpg 是否放行,见测试数据 §10 补充-1) |"),
("PLT_BSC_LC_074", "备注",
"对应TP-E-013;REQ-019(漏测清单 §1;0 字节为观察项) |",
"对应TP-E-013;REQ-019(漏测清单 §1;0 字节为观察项);[待确认] 合同附件扩展名大小写口径(.PDF/.Jpg 是否放行,见测试数据 §10 补充-1) |"),
# S-001
("PLT_BSC_LC_017", "测试步骤",
"3. 上传营业执照_测试甲.jpg 后再次提交<br>4. 删除已上传的营业执照后再次提交",
"3. 上传营业执照_测试甲.jpg 后再次提交(验证提交不再因营业执照被阻断;完整成功链路由 PLT_BSC_LC_038 覆盖)<br>4. 在新增页重新打开表单(名称改用\"云南测试营业执照校验物流有限公司2\"等新唯一值),上传营业执照后删除该证件,再次提交"),
("PLT_BSC_LC_017", "预期结果",
"3. 上传后提交不再因营业执照阻断并保存成功<br>4. 删除已上传营业执照后提交再次被阻断(删除动作同步清空暂存值)",
"3. 提交不再因营业执照被阻断(阻断原因不再指向营业执照;表单可按 038 用例完成保存)<br>4. 删除已上传营业执照后提交再次被阻断(删除动作同步清空暂存值)"),
# S-002
("PLT_BSC_LC_049", "测试步骤",
"4. 再次点击删除并在确认框中确认",
"4. 再次点击删除并在确认框中确认,记录删除结果(本步完成后 LC-04 即为已逻辑删除状态)"),
("PLT_BSC_LC_054", "备注",
"对应TP-D-006;REQ-013/验收要点 2/6.5 |",
"对应TP-D-006;REQ-013/验收要点 2/6.5;前置承接:LC-04 确认删除由本用例唯一执行(PLT_BSC_LC_049 步骤 4 仅记录结果);若 049 已执行确认删除,本用例前置改为\"LC-04 已逻辑删除\"、步骤 1 改用新造可删除公司 |"),
# S-003 + S-004
("PLT_BSC_LC_061", "测试步骤",
"1. 用\"玉溪测试丁货运代理有限公司\"+ 91530402MA6U2W5J8J 新建公司提交<br>2. 用简称码 YND 新建另一公司提交<br>3. 核对新建成功与列表展示<br>4. 核对导出与统计是否将新旧两家视为同一",
"1. 新造临时公司(\"云南测试重建样本物流有限公司\"+" + NEW_USCC + ",简称码 DL6)并删除该临时公司<br>2. 用与临时公司完全相同的三元组(名称+" + NEW_USCC + "+简称码 DL6)新建公司提交<br>3. 核对新建成功与列表展示<br>4. 核对导出与统计是否将新旧两家视为同一"),
("PLT_BSC_LC_061", "预期结果",
"2. 新建公司与已删除行在数据库并存(deleted=0 与 deleted=1 两条记录),无唯一性误拦<br>3. 列表仅展示新建公司(1 条),导出/统计不混淆新旧",
"2. 新建公司与已删除行在数据库并存(deleted=0 与 deleted=1 各 1 条,共 2 条记录),无唯一性误拦<br>3. 列表仅展示新建公司(1 条,不含已删除行),导出/统计不混淆新旧"),
("PLT_BSC_LC_061", "备注",
"对应TP-D-013;BR-01+BR-04 组合/REQ-009 |",
"对应TP-D-013;BR-01+BR-04 组合/REQ-009;本用例为\"已删除后三元组复用\"的唯一创建执行点(PLT_BSC_LC_034/035/036 不得再创建同名/同码/同简称码公司,顺序执行时以本用例的重建记录为准) |"),
("PLT_BSC_LC_034", "备注",
"对应TP-B-015;REQ-009/BR-01 |",
"对应TP-B-015;REQ-009/BR-01;执行顺序:本用例创建的重建记录与 PLT_BSC_LC_061 互斥,二者只执行其一(推荐以 061 为唯一重建执行点,本用例改为核对 061 已创建记录) |"),
("PLT_BSC_LC_035", "备注",
"对应TP-B-016;REQ-009/BR-01(跨机构同码场景见 PLT_TMS_LC_057/061) |",
"对应TP-B-016;REQ-009/BR-01(跨机构同码场景见 PLT_TMS_LC_057/061);执行顺序:本用例的同码重建与 PLT_BSC_LC_061 互斥,二者只执行其一(推荐以 061 为唯一重建执行点) |"),
("PLT_BSC_LC_036", "备注",
"对应TP-B-017;BR-01/REQ-009;[待确认] 简称码空值是否参与全平台唯一、DB 唯一约束对 NULL/空串的处理语义(口径③,见分析 11.2 #4) |",
"对应TP-B-017;BR-01/REQ-009;[待确认] 简称码空值是否参与全平台唯一、DB 唯一约束对 NULL/空串的处理语义(口径③,见分析 11.2 #4);执行顺序:本用例的简称码重建与 PLT_BSC_LC_061 互斥,二者只执行其一(推荐以 061 为唯一重建执行点) |"),
# S-005
("PLT_BSC_LC_052", "测试步骤",
"1. 构造\"仅有待生效合同\"公司(用 LC-02 移除引用后重试或新造公司)发起删除<br>2. 构造\"仅有已过期合同\"公司发起删除",
"1. 新造公司 A(仅挂待生效合同、无运单/货源引用)发起删除<br>2. 新造公司 B(仅挂已过期合同、无运单/货源引用)发起删除"),
("PLT_BSC_LC_052", "预期结果",
"1. 仅有待生效合同时删除不因合同条件阻断(提示原因不含生效合同)<br>2. 仅有已过期合同时同样不因合同条件阻断",
"1. 公司 A 删除成功(deleted=1、列表消失),提示原因不含\"生效合同\";若产品口径为阻断则按双分支记录实际行为<br>2. 公司 B 删除成功(deleted=1、列表消失),提示原因不含\"生效合同\";若产品口径为阻断则按双分支记录实际行为"),
# S-006
("PLT_BSC_LC_067", "测试步骤",
"4. 在 LC-03 下新增另一条编号 HT-2026-0001 复核允许性",
"4. 在 LC-03 下再次新增编号 HT-2026-0001,验证同公司唯一性仍然生效"),
# S-007
("PLT_TMS_LC_037", "预期结果",
"已删除公司是否出现在下拉按快照追溯口径记录实际行为",
"已删除公司不出现在打款筛选下拉(与 PLT_BSC_LC_056/TP-D-008/SS-08 一致)"),
# S-008
("PLT_BSC_LC_069", "测试步骤",
"4. 核对每次弹窗状态与提示",
"4. 核对每次弹窗状态与提示<br>5. 分别留空签订时间、生效时间、过期时间各保存一次"),
("PLT_BSC_LC_069", "预期结果",
"4. 所有阻断场景弹窗不关闭、已填内容保留;数据库无非法记录落库",
"4. 所有阻断场景弹窗不关闭、已填内容保留;数据库无非法记录落库<br>5. 三项时间任一为空保存均被阻断、错误字段就近标红,弹窗不关闭、数据库无非法记录(样本 CD-04)"),
("PLT_BSC_LC_069", "备注",
"对应TP-E-008;BR-03/验收要点 4 |",
"对应TP-E-008;BR-03/验收要点 4;CD-04 |"),
# S-009
("PLT_BSC_LC_020", "测试步骤",
"1. 营业执照依次上传 .jpg/.jpeg/.png/.pdf 四个文件<br>2. 营业执照上传 .gif/.docx/.txt/无扩展名/.bmp 文件",
"1. 营业执照与道路运输经营许可证分别依次上传 .jpg/.jpeg/.png/.pdf 四个文件<br>2. 营业执照与道路运输经营许可证分别上传 .gif/.docx/.txt/无扩展名/.bmp 文件"),
("PLT_BSC_LC_020", "预期结果",
"1. 营业执照 jpg/jpeg/png/pdf 四格式逐一上传成功并可预览<br>2. 营业执照对 gif/docx/txt/无扩展名/bmp 拒绝并提示格式白名单(注意 bmp 不在证件白名单)",
"1. 营业执照与许可证 jpg/jpeg/png/pdf 四格式逐一上传成功并可预览<br>2. 营业执照与许可证对 gif/docx/txt/无扩展名/bmp 拒绝并提示格式白名单(注意 bmp 不在证件白名单)"),
("PLT_BSC_LC_020", "备注",
"对应TP-B-005;REQ-006(与合同附件白名单差异见 DOC-02 说明) |",
"对应TP-B-005;REQ-006(与合同附件白名单差异见 DOC-02 说明);DOC-07 许可证四格式样本 |"),
# O-001
("PLT_BSC_LC_010", "备注",
"(漏收清单 §4 分页)",
"(漏测清单 §4 分页)"),
]
# ---------- 执行 ----------
lines = CASES.read_text(encoding="utf-8").splitlines(keepends=True)
by_case: dict[str, int] = {}
for i, line in enumerate(lines):
if line.startswith("| PLT_"):
by_case[line.split("|")[1].strip()] = i
applied = 0
for case_id, col, old, new in FIXES:
li = by_case[case_id]
line = lines[li]
cnt = line.count(old)
if cnt != 1:
raise SystemExit(f"❌ {case_id} [{col}] 命中 {cnt} 次(期望 1):{old[:60]!r}")
if new in line:
raise SystemExit(f"❌ {case_id} [{col}] 目标文本已存在,跳过以免重复:{new[:60]!r}")
lines[li] = line.replace(old, new)
applied += 1
print(f"✅ {case_id} [{col}] 已修复")
CASES.write_text("".join(lines), encoding="utf-8")
print(f"\n共应用 {applied} 处修复 -> {CASES}")