test(e2e): 新增填报流程端到端脚本与测试计划
既有 37 个脚本是按模块切片的(门禁/草稿/提交/审核各一个),有三处固定盲区: 跨步骤的状态轨迹没人断言、切片之间那条缝(驳回后改了字段再交)、以及脚本 docstring 自述与实际断言不符(e2e-m3-draft.py:11 自述的那条断言全文没有)。 docs/11 给出 A~J 十组覆盖矩阵与判据口径(含用 grep 核对实际断言、不读自述的 规程),scripts/e2e-m3-flow.py 只补这三处、其余交给既有脚本,并钉住 F-125 / F-128 的现状(XFAIL)。verify-all 的脚本数口径随之变成 38。 配套 scripts/dev-reveal-roster-idcard.py:L3-B 走查要在门禁界面手输身份证, 而明文只在建夹具那一刻存在过(库里是 AES 密文 + 脱敏 + HMAC 索引), 此脚本只读解密打印,不入库;用完连同夹具任务一起 --clean。
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""临时脚本(只读):解出本轮走查夹具(e2e-m3-flow.py 建的 taskMain)名册行身份证明文。
|
||||
|
||||
用途:L3-B 浏览器走查要在门禁界面里**手动输入姓名 + 身份证号**,
|
||||
而明文只在建夹具的那一刻存在过(库里是 AES 密文 / 脱敏 / HMAC 索引)。
|
||||
dev 的 AES 密钥在 application-dev.yml 里(提交进仓库的开发专用密钥),格式见 AesGcmCipher:
|
||||
Base64( IV(12) || ciphertext || tag(16) )。
|
||||
|
||||
**只读,不写库。** 走查完请连同夹具任务一起清掉(`python scripts/e2e-m3-flow.py --clean <taskId>`)。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
|
||||
if hasattr(sys.stdout, "reconfigure"):
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
TASK_ID = int(sys.argv[1]) if len(sys.argv) > 1 else 2311
|
||||
|
||||
DEV_YML = r"D:\IDEA_Project\xiaotutongxue\backend\xt-server\src\main\resources\application-dev.yml"
|
||||
TEXT = open(DEV_YML, encoding="utf-8").read()
|
||||
AES_KEY = base64.b64decode(re.search(r"aes-key:\s*(\S+)", TEXT).group(1))
|
||||
CIPHER = AESGCM(AES_KEY)
|
||||
|
||||
|
||||
def psql(sql: str) -> list[list[str]]:
|
||||
p = subprocess.run(
|
||||
["docker", "exec", "xt-pg", "psql", "-U", "fill", "-d", "filldb",
|
||||
"-A", "-F", "\t", "-P", "pager=off", "-t", "-c", sql],
|
||||
capture_output=True,
|
||||
)
|
||||
if p.returncode != 0:
|
||||
raise SystemExit(p.stderr.decode("utf-8", "replace"))
|
||||
# ⚠️ 不能对整段输出 .strip() —— psql 的 -A 模式在**末尾字段为空**时会留下结尾制表符,
|
||||
# 整段 strip 会把它吃掉,于是"未绑定"的那一行少一列、解包直接报
|
||||
# `ValueError: not enough values to unpack`(而这个报错看起来像解密失败)。
|
||||
out = p.stdout.decode("utf-8", "replace")
|
||||
return [ln.split("\t") for ln in out.splitlines() if ln.strip()]
|
||||
|
||||
|
||||
def decrypt(cipher_b64: str) -> str:
|
||||
raw = base64.b64decode(cipher_b64.strip())
|
||||
return CIPHER.decrypt(raw[:12], raw[12:], None).decode("utf-8")
|
||||
|
||||
|
||||
rows = psql(f"""
|
||||
SELECT id, real_name, COALESCE(id_card_no,''), COALESCE(id_card_mask,''),
|
||||
COALESCE(bind_user_id::text,'')
|
||||
FROM collect_roster
|
||||
WHERE deleted = 0 AND task_id = {TASK_ID}
|
||||
ORDER BY id
|
||||
""")
|
||||
|
||||
print(f"任务 {TASK_ID} 的名册(走查用;只打印,不入库)")
|
||||
print("名册行 | 姓名 | 身份证(明文) | 脱敏 | 绑定用户")
|
||||
for r in rows:
|
||||
rid, name, enc = r[0], r[1], r[2]
|
||||
mask = r[3] if len(r) > 3 else ""
|
||||
bind = r[4] if len(r) > 4 else ""
|
||||
try:
|
||||
plain = decrypt(enc)
|
||||
except Exception as e: # noqa: BLE001
|
||||
print(f"{rid} | {name} | [解不开:{type(e).__name__}] | {mask} | {bind or '未绑定'}")
|
||||
continue
|
||||
print(f"{rid} | {name} | {plain} | {mask} | {bind or '未绑定'}")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,11 +24,12 @@
|
||||
|
||||
```bash
|
||||
python scripts/verify-all.py # 全部(跳过需要外部前置的,并说明)
|
||||
python scripts/verify-all.py --with-e2e # 连 37 个脚本的接口断言一起跑(需要后端在跑)
|
||||
python scripts/verify-all.py --with-e2e # 连 38 个脚本的接口断言一起跑(需要后端在跑)
|
||||
python scripts/verify-all.py --quick # 只跑不需要任何前置的五项
|
||||
```
|
||||
|
||||
> 脚本数与断言总数会随需求变化(2026-10 需求收敛后是 **37 个脚本**,断言总数以本命令
|
||||
> 脚本数与断言总数会随需求变化(2026-10 需求收敛后是 **37 个脚本**,加上
|
||||
> `e2e-m3-flow.py` 后是 **38 个**;断言总数以本命令
|
||||
> 实际输出为准 —— 别再往文档里抄一个会过期的固定数字)。
|
||||
|
||||
退出码:0 = 全过;1 = 有失败(**跳过不算失败**,但会明确列出来)。
|
||||
@@ -130,7 +131,7 @@ def main():
|
||||
results.append(("接口断言(E2E)", None, msg))
|
||||
print(" %s%-14s%s %s" % (YELLOW, "接口断言", RESET, msg))
|
||||
elif not args.with_e2e:
|
||||
msg = "**跳过**:要跑就加 `--with-e2e`(37 个脚本、约 10 分钟)"
|
||||
msg = "**跳过**:要跑就加 `--with-e2e`(38 个脚本、约 10 分钟)"
|
||||
results.append(("接口断言(E2E)", None, msg))
|
||||
print(" %s%-14s%s %s" % (YELLOW, "接口断言", RESET, msg))
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user