You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
4.6 KiB

2 days ago
# -*- coding: utf-8 -*-
"""票 05 收尾:请求示例节残留占位标记处置 + 全量验证重跑(修 V7 路径/解析)。"""
from __future__ import annotations
import io
import json
import re
import sys
from pathlib import Path
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
A4 = Path('D:/code/crm-api-docs/A4 客户管理')
# ---------- 1) 请求示例标记行处置 ----------
FIX_TRUE = '// 请求参数(E2E 实测载荷)' # 原行含「E2E 实测值注入」:载荷本就是实测真值
FIX_SAMPLE = '// 请求参数示例' # 原行为编造示例值
fixed_t = fixed_s = 0
for p in sorted(A4.rglob('*.bru')):
if p.name == 'folder.bru':
continue
txt = p.read_text(encoding='utf-8')
if '非真实返回' not in txt:
continue
lines = txt.splitlines()
hit = False
for i, l in enumerate(lines):
if '非真实返回' not in l:
continue
assert l.strip().startswith('// 示例数据'), f'非独立标记行 {p.relative_to(A4)}:{i+1}: {l}'
if 'E2E 实测值注入' in l:
lines[i] = l.replace(l.strip(), FIX_TRUE)
fixed_t += 1
else:
lines[i] = l.replace(l.strip(), FIX_SAMPLE)
fixed_s += 1
hit = True
if hit:
p.write_text('\n'.join(lines) + ('\n' if txt.endswith('\n') else ''),
encoding='utf-8', newline='')
print(f'[F] 请求示例标记行处置:实测载荷版 {fixed_t} 行、编造示例版 {fixed_s}')
# ---------- 2) 全量验证 ----------
print('== 验证 ==')
all_files = [p for p in A4.rglob('*.bru') if p.name != 'folder.bru']
ph = [str(p.relative_to(A4)) for p in all_files if '非真实返回' in p.read_text(encoding='utf-8')]
print(f'[V1] 「非真实返回」残留 = {len(ph)}(目标 0){ph if ph else ""}')
sec_bad, tv = [], 0
for p in all_files:
t = p.read_text(encoding='utf-8')
n = len(re.findall(r'^\s*## 响应示例', t, re.M))
if n != 1:
sec_bad.append(f'{p.relative_to(A4)} ×{n}')
if 'E2E 实测真值' in t:
tv += 1
print(f'[V2] 响应示例节≠1 = {len(sec_bad)}(目标 0){sec_bad if sec_bad else ""}')
print(f'[V3] 含真值标记 = {tv}/{len(all_files)}')
n_ec = sum(1 for p in all_files if '## 错误码' in p.read_text(encoding='utf-8'))
print(f'[V4] 错误码节 = {n_ec}(基线 78)')
keys_ok = sum(1 for p in all_files if re.search(r'^\s*`\s*(GET|POST)\s+(/[^\s`]+)\s*`', p.read_text(encoding='utf-8'), re.M))
print(f'[V5] 对账钥匙完好 = {keys_ok}/{len(all_files)}')
bom = [str(p.relative_to(A4)) for p in all_files if p.read_bytes()[:3] == b'\xef\xbb\xbf']
print(f'[V6] BOM = {len(bom)}(目标 0){bom if bom else ""}')
# V7 (b) 退化端点抽查:写回后 data 关键字段非空
SPOT = {
'客户交割/客户分配.bru': 'failures',
'客户公海/失败疑似重复明细.bru': 'data-list',
'我的客户/客户导入/失败疑似重复明细.bru': 'data-list',
'客户详情/联系人图谱/图谱全量读.bru': 'nodes',
'客户详情/联系人/快速添加联系人.bru': 'failedRows',
'我的客户/快速创建客户.bru': 'similarHits',
'客户详情/联系人/页内批量编辑.bru': 'successCount',
}
for rel, field in SPOT.items():
t = (A4 / rel).read_text(encoding='utf-8')
mm = re.search(r'## 响应示例\s*\n\s*\n\s*// 示例数据(E2E 实测真值)[^\n]*\n\s*```json\n(.*?)\n\s*```', t, re.S)
ok = '?'
if mm:
try:
payload = json.loads(mm.group(1))
d = payload.get('data')
if field == 'data-list':
ok = '非空' if isinstance(d, list) and len(d) >= 1 else f'退化:{str(d)[:50]}'
elif isinstance(d, dict):
v = d.get(field)
ok = '非空' if v else f'空:{field}={v}'
else:
ok = f'形态异常:{str(d)[:50]}'
except Exception as e:
ok = f'解析失败:{e}'
else:
ok = '⚠ 未匹配响应示例块'
print(f'[V7] {rel}: {field} {ok}')
for rel in ['客户公海/下载导入模板.bru', '我的客户/客户导入/下载导入模板.bru',
'客户详情/联系人导入/下载导入模板.bru']:
t = (A4 / rel).read_text(encoding='utf-8')
print(f'[V8] {rel}: 二进制说明 {"" if "二进制文件流" in t else ""}')
for rel in ['客户总览/workspace 列表分页.bru', '我的客户/workspace 列表分页.bru',
'客户公海/workspace 列表分页.bru']:
t = (A4 / rel).read_text(encoding='utf-8')
print(f'[V9] {rel}: total 注记 {"" if "实测 total=" in t else ""}')
print('== 票 05 收尾完成 ==')