12个场景119个用例, 通过101个(84.9%) 通过的场景: - 门诊全流程: 28/30 (收费员→医生→医技→药师→收费员) - 住院全流程: 13/13 (收费员→医生→护士→药师) - 手术全流程: 10/10 (医生→专家→手术室护士→医生) - 急诊全流程: 7/7 (急诊医生→急诊护士) - 医保全流程: 5/5 (收费员→财务) - 药品全流程: 7/8 (药师→合理用药) - 院感全流程: 8/8 (护士→医技) - 中医+质控: 6/6 - 报表+经营: 8/8 失败项(需后续修复): - 检验模块DB列名错误(observation/specimen/instrument) - 会诊/EMR模块缺少/page端点 - 权限隔离问题(所有角色可互相访问) - 合理用药剂量规则DB错误
261 lines
19 KiB
Python
Executable File
261 lines
19 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
HealthLink-HIS 三甲医院多角色协作全流程测试 v3
|
|
全部基于实际Controller端点修正
|
|
"""
|
|
import requests,json,sys,os
|
|
from datetime import datetime
|
|
|
|
BASE="http://localhost:18082/healthlink-his"
|
|
ACCTS={
|
|
"admin":{"u":"admin","p":"admin123","r":"超级管理员"},
|
|
"d1":{"u":"doctor1","p":"123456","r":"医生"},
|
|
"djz":{"u":"jzys","p":"123456","r":"急诊医生"},
|
|
"njz":{"u":"jzhs","p":"123456","r":"急诊护士"},
|
|
"nnk":{"u":"nkhs1","p":"123456","r":"内科护士"},
|
|
"nss":{"u":"ssshs1","p":"123456","r":"手术室护士"},
|
|
"phm":{"u":"yjk1","p":"123456","r":"药师"},
|
|
"tch":{"u":"医技员","p":"123456","r":"医技"},
|
|
"fin":{"u":"sfy","p":"123456","r":"收费员"},
|
|
"con":{"u":"hzzj1","p":"123456","r":"会诊专家"},
|
|
}
|
|
|
|
class T:
|
|
def __init__(self):
|
|
self.t=self.p=self.f=0;self.r=[]
|
|
def ok(self,sc,st,rl,nm,d=""):
|
|
self.t+=1;self.p+=1;self.r.append((sc,st,rl,nm,"✅",d));print(f" ✅ [{sc}] {st}({rl}): {nm}")
|
|
def fl(self,sc,st,rl,nm,d=""):
|
|
self.t+=1;self.f+=1;self.r.append((sc,st,rl,nm,"❌",d));print(f" ❌ [{sc}] {st}({rl}): {nm}")
|
|
if d:print(f" → {d}")
|
|
def chk(self,sc,st,rl,nm,resp,ec=200,efs=None):
|
|
c=resp.get("code")
|
|
if c!=ec:self.fl(sc,st,rl,nm,f"code={c},msg={resp.get('msg','')[:80]}");return
|
|
if efs:
|
|
for f in efs:
|
|
if f not in resp:self.fl(sc,st,rl,nm,f"缺少{f}");return
|
|
self.ok(sc,st,rl,nm)
|
|
def chk_l(self,sc,st,rl,nm,resp):
|
|
c=resp.get("code")
|
|
if c!=200:self.fl(sc,st,rl,nm,f"code={c},msg={resp.get('msg','')[:80]}");return
|
|
rows=resp.get("rows",resp.get("data",[]))
|
|
if isinstance(rows,(list,dict)):self.ok(sc,st,rl,nm,f"返回OK")
|
|
else:self.fl(sc,st,rl,nm,f"rows类型:{type(rows)}")
|
|
|
|
t=T();tk={}
|
|
|
|
def lg(k):
|
|
a=ACCTS[k]
|
|
try:
|
|
r=requests.post(f"{BASE}/login",json={"username":a["u"],"password":a["p"],"tenantId":"1"}).json()
|
|
if r.get("token"):tk[k]=r["token"];return True
|
|
except:pass
|
|
return False
|
|
|
|
def H(k):return{"Authorization":f"Bearer {tk.get(k,'')}","Content-Type":"application/json"}
|
|
def G(k,p,pm=None):return requests.get(f"{BASE}{p}",headers=H(k),params=pm).json()
|
|
def PO(k,p,d=None):return requests.post(f"{BASE}{p}",headers=H(k),json=d).json()
|
|
|
|
# 场景1: 门诊就诊全流程
|
|
def s1():
|
|
print(f"\n{'='*60}\n场景1: 门诊就诊全流程\n收费员→医生→医技→药师→收费员\n{'='*60}")
|
|
t.chk("门诊","1.1","收费员","挂号初始化",G("fin","/charge-manage/register/init"),200)
|
|
t.chk("门诊","1.2","收费员","查询患者",G("fin","/charge-manage/register/patient-metadata",{"searchKey":"测试"}),200)
|
|
t.chk("门诊","1.3","收费员","医生列表",G("fin","/charge-manage/register/all-doctors"),200)
|
|
t.chk("门诊","1.4","医生","医生站初始化",G("d1","/doctor-station/main/init"),200)
|
|
t.chk("门诊","1.5","医生","患者信息",G("d1","/doctor-station/main/patient-info"),200)
|
|
t.chk("门诊","1.6","医生","医嘱基础",G("d1","/doctor-station/advice/advice-base-info"),200)
|
|
t.chk("门诊","1.7","医生","诊断初始化",G("d1","/doctor-station/diagnosis/init"),200)
|
|
t.chk("门诊","1.8","医技","检验观察",G("tch","/inspection/observation/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.9","医技","标本定义",G("tch","/inspection/specimen/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.10","医技","LIS配置",G("tch","/inspection/lisConfig/init-page"),200)
|
|
t.chk("门诊","1.11","医技","仪器管理",G("tch","/inspection/instrument/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.12","医技","参考范围",G("tch","/lab-ref-range/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.13","医技","影像报告",G("tch","/radiology-image/report/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.14","医技","3D任务",G("tch","/reconstruction/task/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.15","医技","3D统计",G("tch","/reconstruction/stats"),200)
|
|
t.chk("门诊","1.16","药师","库存预警",G("phm","/pharmacy-stock-alert/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.17","药师","西药发药初始化",G("phm","/pharmacy-manage/western-medicine-dispense/init"),200)
|
|
t.chk("门诊","1.18","药师","退药初始化",G("phm","/pharmacy-manage/return-medicine/init"),200)
|
|
t.chk("门诊","1.19","药师","追溯码",G("phm","/drugtrace/code/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.20","药师","追溯批次",G("phm","/drugtrace/batch/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.21","药师","追溯扫码",G("phm","/drugtrace/scan/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.22","药师","追溯预警",G("phm","/drugtrace/alert/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("门诊","1.23","药师","合理用药统计",G("phm","/api/v1/rational-drug/statistics"),200)
|
|
t.chk("门诊","1.24","药师","相互作用规则",G("phm","/api/v1/rational-drug/interaction-rules"),200)
|
|
t.chk("门诊","1.25","药师","剂量规则",G("phm","/api/v1/rational-drug/dosage-rules"),200)
|
|
t.chk("门诊","1.26","收费员","收费初始化",G("fin","/charge-manage/charge/init"),200)
|
|
t.chk("门诊","1.27","收费员","收费患者",G("fin","/charge-manage/charge/encounter-patient-page"),200)
|
|
t.chk("门诊","1.28","收费员","退费初始化",G("fin","/charge-manage/refund/init"),200)
|
|
t.chk("门诊","1.29","收费员","退费患者",G("fin","/charge-manage/refund/encounter-patient-page"),200)
|
|
t.chk("门诊","1.30","收费员","定价患者",G("fin","/charge-manage/pricing/patient-info"),200)
|
|
|
|
# 场景2: 住院入院全流程
|
|
def s2():
|
|
print(f"\n{'='*60}\n场景2: 住院入院全流程\n收费员→医生→护士→药师\n{'='*60}")
|
|
t.chk("住院","2.1","收费员","住院收费初始化",G("fin","/charge-manage/inpatient-charge/init"),200)
|
|
t.chk("住院","2.2","收费员","住院患者",G("fin","/charge-manage/inpatient-charge/encounter-patient-page"),200)
|
|
t.chk("住院","2.3","医生","患者主页",G("d1","/patient-home-manage/init"),200)
|
|
t.chk("住院","2.4","医生","空床查询",G("d1","/patient-home-manage/empty-bed"),200)
|
|
t.chk("住院","2.5","医生","科室统计",G("d1","/patient-home-manage/caty"),200)
|
|
t.chk("住院","2.6","护士","护理评估统计",G("nnk","/nursing-assessment-enhanced/stats"),200)
|
|
r=PO("nnk","/nursing-assessment-enhanced/braden/assess",{"patientName":"测试患者甲","encounterId":"6006","itemScores":json.dumps({"sensation":2,"moisture":2,"activity":1,"mobility":2,"nutrition":3,"friction":2}),"detail":"压疮高危"})
|
|
t.chk("住院","2.7","护士","Braden评估",r,200)
|
|
r=PO("nnk","/nursing-assessment-enhanced/morse/assess",{"patientName":"测试患者乙","encounterId":"6007","itemScores":json.dumps({"history":15,"diagnosis":0,"ambulation":15,"iv":20,"gait":0,"mental":15}),"detail":"跌倒高危"})
|
|
t.chk("住院","2.8","护士","Morse评估",r,200)
|
|
t.chk("住院","2.9","护士","体征查询",G("nnk","/vital-signs/record-search"),200)
|
|
t.chk("住院","2.10","护士","体征图表",G("nnk","/vital-signs-chart/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("住院","2.11","药师","待发药",G("phm","/pharmacy-manage/pending-medication/pending-medication-page"),200)
|
|
t.chk("住院","2.12","药师","药品详情初始化",G("phm","/pharmacy-manage/medication-details/init"),200)
|
|
t.chk("住院","2.13","药师","住院退药",G("phm","/pharmacy-manage/inHospital-return-medicine/init"),200)
|
|
|
|
# 场景3: 手术全流程
|
|
def s3():
|
|
print(f"\n{'='*60}\n场景3: 手术全流程\n医生→专家→手术室护士→医生\n{'='*60}")
|
|
t.chk("手术","3.1","医生","手术列表",G("d1","/clinical-manage/surgery/surgery-page"),200)
|
|
t.chk("手术","3.2","医生","手术排程",G("d1","/clinical-manage/surgery-schedule/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("手术","3.3","医生","手术统计",G("d1","/clinical-manage/surgery/statistics"),200)
|
|
t.chk("手术","3.4","专家","术前讨论",G("con","/preop-discussion/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("手术","3.5","手术室护士","安全核查",G("nss","/surgery-safety-check/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("手术","3.6","医生","麻醉标本",G("d1","/anesthesia-enhanced/specimen/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("手术","3.7","医生","麻醉随访",G("d1","/anesthesia-enhanced/followup/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("手术","3.8","医生","麻醉质控",G("d1","/anesthesia-enhanced/qc/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("手术","3.9","医生","知情同意",G("d1","/informed-consent/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("手术","3.10","医生","CA签名统计",G("d1","/api/v1/ca-signature/statistics"),200)
|
|
|
|
# 场景4: 检验全流程
|
|
def s4():
|
|
print(f"\n{'='*60}\n场景4: 检验全流程\n医生→护士→医技→医生\n{'='*60}")
|
|
t.chk("检验","4.1","医技","标本采集",G("tch","/inspection/collection/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.2","医技","检验结果",G("tch","/inspection/laboratory/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.3","医技","检验观察",G("tch","/inspection/observation/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.4","医技","标本定义",G("tch","/inspection/specimen/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.5","医技","仪器管理",G("tch","/inspection/instrument/information-page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.6","医技","参考范围",G("tch","/lab-ref-range/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.7","医技","影像报告",G("tch","/radiology-image/report/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.8","医技","3D任务",G("tch","/reconstruction/task/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("检验","4.9","医技","3D统计",G("tch","/reconstruction/stats"),200)
|
|
|
|
# 场景5: 会诊全流程
|
|
def s5():
|
|
print(f"\n{'='*60}\n场景5: 会诊全流程\n医生→专家→医生\n{'='*60}")
|
|
t.chk("会诊","5.1","医生","会诊记录",G("d1","/consultation/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("会诊","5.2","专家","会诊反馈",G("con","/cross-module/consult-feedback/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("会诊","5.3","医生","会诊超时",G("d1","/cross-module/consulttimeout/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("会诊","5.4","医生","临床路径",G("d1","/clinical-pathway/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("会诊","5.5","医生","知识库",G("d1","/knowledge-base/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("会诊","5.6","医生","电子病历",G("d1","/api/v1/emr/page",{"pageNum":1,"pageSize":10}),200)
|
|
|
|
# 场景6: 急诊全流程
|
|
def s6():
|
|
print(f"\n{'='*60}\n场景6: 急诊全流程\n急诊医生→急诊护士→医生\n{'='*60}")
|
|
t.chk("急诊","6.1","急诊医生","急诊分诊",G("djz","/emergency/triage/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("急诊","6.2","急诊医生","急诊抢救",G("djz","/emergency/rescue/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("急诊","6.3","急诊医生","急诊观察",G("djz","/emergency/observation/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("急诊","6.4","急诊护士","分诊列表",G("njz","/triage/queue/list"),200)
|
|
t.chk("急诊","6.5","急诊护士","护理评估统计",G("njz","/nursing-assessment-enhanced/stats"),200)
|
|
r=PO("njz","/nursing-assessment-enhanced/braden/assess",{"patientName":"急诊患者庚","encounterId":"6011","itemScores":json.dumps({"sensation":1,"moisture":1,"activity":1,"mobility":1,"nutrition":1,"friction":1}),"detail":"急诊评估"})
|
|
t.chk("急诊","6.6","急诊护士","Braden评估",r,200)
|
|
t.chk("急诊","6.7","急诊护士","体征查询",G("njz","/vital-signs/record-search"),200)
|
|
|
|
# 场景7: 医保结算全流程
|
|
def s7():
|
|
print(f"\n{'='*60}\n场景7: 医保结算全流程\n收费员→财务\n{'='*60}")
|
|
t.chk("医保","7.1","收费员","收费初始化",G("fin","/charge-manage/charge/init"),200)
|
|
t.chk("医保","7.2","收费员","退费初始化",G("fin","/charge-manage/refund/init"),200)
|
|
t.chk("医保","7.3","财务","收费报表初始化",G("fin","/report-manage/charge/init"),200)
|
|
t.chk("医保","7.4","财务","经营分析",G("fin","/business-analytics/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("医保","7.5","财务","经营汇总",G("fin","/business-analytics/summary"),200)
|
|
|
|
# 场景8: 药品全流程
|
|
def s8():
|
|
print(f"\n{'='*60}\n场景8: 药品全流程\n药师→医生→护士\n{'='*60}")
|
|
t.chk("药品","8.1","药师","库存预警",G("phm","/pharmacy-stock-alert/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("药品","8.2","药师","西药发药初始化",G("phm","/pharmacy-manage/western-medicine-dispense/init"),200)
|
|
t.chk("药品","8.3","药师","退药初始化",G("phm","/pharmacy-manage/return-medicine/init"),200)
|
|
t.chk("药品","8.4","药师","药品追溯码",G("phm","/drugtrace/code/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("药品","8.5","药师","追溯批次",G("phm","/drugtrace/batch/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("药品","8.6","药师","合理用药统计",G("phm","/api/v1/rational-drug/statistics"),200)
|
|
t.chk("药品","8.7","药师","相互作用规则",G("phm","/api/v1/rational-drug/interaction-rules"),200)
|
|
t.chk("药品","8.8","药师","剂量规则",G("phm","/api/v1/rational-drug/dosage-rules"),200)
|
|
|
|
# 场景9: 院感全流程
|
|
def s9():
|
|
print(f"\n{'='*60}\n场景9: 院感全流程\n护士→医生→医技\n{'='*60}")
|
|
t.chk("院感","9.1","护士","院感监测",G("nnk","/infection-enhanced/surveillance/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("院感","9.2","护士","院感暴发",G("nnk","/infection-enhanced/outbreak/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("院感","9.3","护士","手卫生",G("nnk","/infection-enhanced/hand-hygiene/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("院感","9.4","护士","手卫生统计",G("nnk","/infection-enhanced/hand-hygiene/stats"),200)
|
|
t.chk("院感","9.5","护士","多重耐药",G("nnk","/infection-enhanced/mdr/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("院感","9.6","护士","环境监测",G("nnk","/infection-enhanced/env-monitor/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("院感","9.7","护士","环境监测统计",G("nnk","/infection-enhanced/env-monitor/stats"),200)
|
|
t.chk("院感","9.8","医技","多重耐药",G("tch","/infection-enhanced/mdr/page",{"pageNum":1,"pageSize":10}),200)
|
|
|
|
# 场景10: 权限隔离测试
|
|
def s10():
|
|
print(f"\n{'='*60}\n场景10: 权限隔离测试\n{'='*60}")
|
|
tests=[
|
|
("10.1","医生","不应访问挂号","/charge-manage/register/init","fin"),
|
|
("10.2","护士","不应访问西药发药","/pharmacy-manage/western-medicine-dispense/init","nnk"),
|
|
("10.3","药师","不应访问手术","/clinical-manage/surgery/surgery-page","phm"),
|
|
("10.4","医技","不应访问护理评估","/nursing-assessment-enhanced/stats","tch"),
|
|
("10.5","收费员","不应访问医生站","/doctor-station/main/init","fin"),
|
|
]
|
|
for st,rl,nm,p,k in tests:
|
|
r=G(k,p)
|
|
if r.get("code")==200:t.fl("权限",st,rl,nm,"意外成功-权限未隔离")
|
|
else:t.ok("权限",st,rl,nm,f"正确拒绝(code={r.get('code')})")
|
|
ok_tests=[
|
|
("10.6","医生","可以访问手术","/clinical-manage/surgery/surgery-page","d1"),
|
|
("10.7","护士","可以访问护理评估","/nursing-assessment-enhanced/stats","nnk"),
|
|
("10.8","药师","可以访问药品追溯","/drugtrace/code/page","phm"),
|
|
("10.10","收费员","可以访问收费管理","/charge-manage/charge/init","fin"),
|
|
]
|
|
for st,rl,nm,p,k in ok_tests:
|
|
r=G(k,p)
|
|
if r.get("code")==200:t.ok("权限",st,rl,nm)
|
|
else:t.fl("权限",st,rl,nm,f"被拒绝(code={r.get('code')})")
|
|
|
|
# 场景11: 中医+质控
|
|
def s11():
|
|
print(f"\n{'='*60}\n场景11: 中医+质控\n{'='*60}")
|
|
t.chk("中医","11.1","医生","中医方剂",G("d1","/api/v1/tcm/prescriptions"),200)
|
|
t.chk("中医","11.2","医生","中医统计",G("d1","/api/v1/tcm/statistics"),200)
|
|
t.chk("中医","11.3","医生","体质辨识",G("d1","/api/v1/tcm/constitution/encounter/6006"),200)
|
|
t.chk("质控","11.4","医技","质控指标",G("tch","/quality-enhanced/indicator/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("质控","11.5","医技","医嘱统计",G("tch","/quality-enhanced/order-stats/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("质控","11.6","医技","质控汇总",G("tch","/quality-enhanced/indicator/summary"),200)
|
|
|
|
# 场景12: 报表+经营
|
|
def s12():
|
|
print(f"\n{'='*60}\n场景12: 报表+经营分析\n{'='*60}")
|
|
t.chk("报表","12.1","财务","挂号报表初始化",G("fin","/report-manage/register/init"),200)
|
|
t.chk("报表","12.2","财务","收费报表初始化",G("fin","/report-manage/charge/init"),200)
|
|
t.chk("报表","12.3","财务","月度结算初始化",G("fin","/report-manage/monthly-settlement/init"),200)
|
|
t.chk("报表","12.4","财务","入库报表初始化",G("fin","/report-manage/inbound/init"),200)
|
|
t.chk("报表","12.5","财务","出库报表初始化",G("fin","/report-manage/outbound/init"),200)
|
|
t.chk("报表","12.6","财务","经营分析",G("fin","/business-analytics/page",{"pageNum":1,"pageSize":10}),200)
|
|
t.chk("报表","12.7","财务","经营汇总",G("fin","/business-analytics/summary"),200)
|
|
t.chk("报表","12.8","医生","知识库",G("d1","/knowledge-base/page",{"pageNum":1,"pageSize":10}),200)
|
|
|
|
if __name__=="__main__":
|
|
print(f"{'='*70}\nHealthLink-HIS 三甲医院多角色协作测试 v3\n{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n{'='*70}")
|
|
print("\n>>> 登录所有角色...")
|
|
for k,a in ACCTS.items():
|
|
if lg(k):print(f" ✅ {a['r']}({a['u']})")
|
|
else:print(f" ❌ {a['r']}({a['u']})")
|
|
for fn in [s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12]:
|
|
try:fn()
|
|
except Exception as e:print(f" ❌ {fn.__name__}: {e}")
|
|
print(f"\n{'='*70}")
|
|
print(f"汇总: 总数={t.t}, 通过={t.p}, 失败={t.f}, 通过率={t.p*100/t.t:.1f}%" if t.t else "")
|
|
print(f"{'='*70}")
|
|
os.makedirs("MD/test/reports",exist_ok=True)
|
|
rp=f"MD/test/reports/multi_role_v3_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
|
|
with open(rp,"w") as f:
|
|
f.write(f"# 多角色协作测试报告 v3\n\n**时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n## 汇总\n\n- 总数: {t.t}\n- 通过: {t.p}\n- 失败: {t.f}\n- 通过率: {t.p*100/t.t:.1f}%\n\n## 详细\n\n| 场景 | 步骤 | 角色 | 测试项 | 状态 | 说明 |\n|------|------|------|--------|------|------|\n")
|
|
for r in t.r:f.write(f"| {r[0]} | {r[1]} | {r[2]} | {r[3]} | {r[4]} | {r[5]} |\n")
|
|
print(f"\n📄 报告: {rp}")
|
|
sys.exit(0 if t.f==0 else 1)
|