山东大学创新实训个人博客8:系统测试
这段时间的重点主要放在康复智能体模块、多模态文件上传流程以及后台管理系统的闭环跑通上。这几天虽然修的都是一些看似分散的 Bug,但本质上都在解决不同服务间状态不同步、接口契约不一致以及跨端超时的问题。以下是本次系统测试过程中的核心排障复盘。
一、康复多模态请求超时与配置分离
测试中最突出的现象是,康复智能体的 /rehab-api/generate 接口经常在 Java 端报错超时,但 Python 端后台实际还在生成。
经过排查,发现 SpringBoot 端调用 FastAPI 时,错误复用了导航接口的短超时配置(30秒)。康复生成需要经历 OCR 解析、文本提取、知识库检索和模型生成,耗时本身就长。同时,由于底层模型从百川切换到了 Qwen,Qwen SDK 默认的 30 秒超时也成了内部瓶颈。
修复方案:将不同业务场景的超时彻底隔离。在 SpringBoot 后端配置中,新增了专门针对康复接口的较长超时参数:
# 康复模块独立超时配置
integration.fastapi.rehab.generate-timeout-seconds=300
integration.fastapi.rehab.plans-timeout-seconds=120
在 Python 侧,也为文本模型调用增加了独立的环境配置:
QWEN_TEXT_TIMEOUT_SECONDS = 120
_RUNTIME.run_qwen_prompt(prompt, timeout=QWEN_TEXT_TIMEOUT_SECONDS)
二、康复日程生成的“本地化”改造
在测试生成康复日程(/rehab-api/plans)时,原系统完全依赖大模型来将处方结构化为日程。遇到复杂的逻辑(如“每日3次,共18次”),模型往往无法稳定地展开成每一条具体的日程,而且容易引发超时。
修复方案:调整架构,改为“本地规则解析优先,大模型兜底”。前端的接口输出被严格约束为“用药、复查、禁忌”三段纯文本。系统拿到文本后,先通过正则拆解药品和次数,在本地推断并生成执行时间:
// 本地解析每日次数并生成执行时间
if (timesPerDay == 3) {
createSchedule(taskId, "08:00");
createSchedule(taskId, "13:00");
createSchedule(taskId, "19:00");
}
只有当本地正则解析失败时,才会调用大模型进行兜底。这种做法极大地提升了日程生成的确定性和速度,有效避免了等待模型导致的 Java 端超时。
三、上传文件契约对齐与丢失扩展名
在安卓端测试上传处方图和症状图时,发现后端落库到 file_index 表里的文件名都没有扩展名(如 .jpg 或 .png),这使得后续的文件预览和分类变得极不稳定。
排查结果:安卓端在选择图库文件时,直接提取了 uri.lastPathSegment,在很多情况下这个值并不包含后缀。同时,前端将处方图片统一按普通的“症状图”类型上传了,业务语义不符。
修复方案:在 RehabilitationScreen.kt 中修改文件读取逻辑,优先读取系统的 DISPLAY_NAME,若读取不到再通过 MIME Type 自动补齐后缀,并将参数约定对齐:
// 修正前端上传的业务类型和文件名补全
val fileType = "PRESCRIPTION"
// 优先获取真实的带有后缀的文件名,防止后端解析为裸文件
val fileName = getFileNameFromUri(uri) ?: "default_prescription.png"
四、管理后台与前端状态同步
测试中还暴露出一些前端界面刷新和管理后台代理的问题。例如,生成康复日程后前端日历不刷新、个人中心头像无法编辑,以及后台管理系统的对话报告路径由于静态目录指向错误而无法查看。
修复方案:
-
安卓端刷新:在日程增删改操作成功后,统一触发
loadSchedules(),让日历直接根据当前年月向服务器拉取最新数据,摒弃本地猜测式的更新。修复了ProfileScreen.kt的文件损坏并补全了头像选图与上传功能。 -
管理后台代理:在
ChatSessionController中新增了一个代理接口,将报告查看通过流的方式从 Python 端透传给浏览器,不再纠结文件的本地物理路径。
// 管理后台代理请求 FastAPI 获取报告流
@GetMapping("/admin-api/chat-sessions/{sessionId}/report")
public void getReport(@PathVariable String sessionId, HttpServletResponse response) {
integrationHttpService.openReportStream(sessionId, response.getOutputStream());
}
经过一整天的联调测试,我们成功完善了绝大多数的功能点,完成了系统测试的整体任务。
更多推荐

所有评论(0)