3. 医疗嵌入式软件开发生命周期与测试嵌入

医疗嵌入式软件(如输液泵控制固件、除颤器能量管理模块、监护仪信号采集固件)的开发过程,既要满足功能正确性,又要满足 IEC 62304 对软件安全分级、开发活动与验证证据的要求。测试不是开发完成后的“最后一道工序”,而是从需求分析开始就嵌入到每个生命周期阶段的并行活动。理解 V 模型、敏捷与迭代开发三种组织方式下测试如何嵌入,以及各阶段的测试入口与出口准则,是建立可追溯、可审计测试体系的基础。

三种生命周期模型中的测试嵌入方式

V 模型把开发活动与验证活动按层级对应:左侧自上而下是需求分析、架构设计、详细设计、编码,右侧自下而上是单元测试、集成测试、系统测试、验收测试。每一层左侧的产出物,都对应右侧一层的验证依据。例如系统需求对应系统测试用例,架构设计对应集成测试用例,详细设计对应单元测试用例。这种对应关系使测试用例的编写可以与设计同步启动,而不是等到编码结束。

敏捷开发把需求拆成小颗粒的用户故事,每个迭代(通常 2~4 周)内完成“需求—设计—编码—测试”闭环。测试嵌入体现为:迭代计划阶段定义验收准则,开发阶段同步编写自动化单元测试与接口测试,迭代结束前完成回归测试。对医疗软件而言,敏捷并不豁免法规要求,仍需在迭代外维护需求追溯、风险分析与设计历史文件。

迭代开发介于两者之间,按增量交付功能,每个增量都经过完整的测试层级。三种模型的共同点是:测试活动与开发活动并行,且每个阶段都有明确的入口准则(可以开始测试的条件)和出口准则(可以结束测试的条件)。

V 模型:开发活动与测试活动的层级对应 需求分析 系统需求 / 风险分析 架构设计 模块划分 / 接口定义 详细设计 函数 / 状态机 / 数据结构 编码实现 C/C++ 源码 / 静态检查 验收测试 临床场景 / 用户需求 系统测试 整机功能 / 性能 / 安全 集成测试 模块接口 / 数据流 单元测试 函数 / 分支 / 边界 各阶段测试入口 / 出口准则(示例) 单元测试:入口 = 函数代码完成且静态检查无严重告警;出口 = 语句覆盖率 ≥ 90%,分支覆盖率 ≥ 80%,缺陷全部关闭。 集成测试:入口 = 相关模块单元测试通过;出口 = 接口数据流验证通过,模块间时序无冲突,缺陷关闭率 100%。 系统测试:入口 = 集成测试通过且版本冻结;出口 = 需求覆盖率 100%,安全相关用例全部通过,遗留缺陷风险可接受。 验收测试:入口 = 系统测试通过且临床场景就绪;出口 = 用户需求逐条验证通过,可追溯性矩阵完整,发布评审通过。

各阶段的测试入口与出口准则

入口准则回答“什么条件下可以开始本阶段测试”,出口准则回答“什么条件下可以结束本阶段测试并进入下一阶段”。准则必须是可检查、可判定的,不能写成“基本完成”“大致通过”这类模糊表述。

需求分析阶段。测试活动主要是需求评审与可测试性分析。入口准则:需求文档完成初稿,风险分析已识别安全相关需求。出口准则:每条需求都有唯一标识、验收准则和对应的测试方法;安全相关需求已标注软件安全等级(A/B/C);需求之间无冲突。例如“输液泵阻塞报警响应时间 ≤ 3 s”这条需求,必须能推导出可测量的测试方法:在管路施加阻塞压力,记录从触发到报警输出的时间。

设计阶段。测试活动是设计评审与测试用例设计。入口准则:架构与详细设计文档完成,接口定义明确。出口准则:每个设计模块都有对应的测试用例;接口的输入输出、时序、异常处理已定义;设计覆盖所有需求。此时可以开始编写单元测试和集成测试用例,而不必等代码完成。

编码阶段。测试活动是静态检查、代码评审和单元测试。入口准则:函数代码完成,编译通过,静态分析无严重告警。出口准则:单元测试语句覆盖率 ≥ 90%、分支覆盖率 ≥ 80%(示例阈值,实际按安全等级调整);所有单元测试通过;代码评审问题已关闭。

集成阶段。测试活动是接口测试和模块间数据流验证。入口准则:相关模块单元测试通过,集成版本可构建。出口准则:模块间接口数据正确传递,时序无冲突,异常路径已验证,集成缺陷全部关闭。

系统测试阶段。测试活动是整机功能、性能、安全性和回归测试。入口准则:集成测试通过,版本冻结,测试环境与临床使用环境一致。出口准则:需求覆盖率 100%,安全相关测试用例全部通过,遗留缺陷的风险等级经评审可接受,回归测试无新增失败。

可追溯性矩阵的建立

可追溯性矩阵(Traceability Matrix, TM)是把需求、设计、代码、测试用例、缺陷和风险连接起来的表格。它的作用是:证明每条需求都被实现和验证,每个测试用例都能追溯到需求,每个缺陷都能定位到受影响的需求和测试。IEC 62304 要求制造商建立并维护这种追溯关系。

建立 TM 的实用做法是:在需求管理工具(如 DOORS、Jama、Polarion)或结构化表格中,为每条需求分配唯一 ID(如 SRS-001),然后逐列填写对应的设计 ID、代码文件/函数、测试用例 ID、测试结果和缺陷 ID。双向追溯是关键:从需求能找到测试,从测试也能回到需求。

下面给出一份可直接参考的可追溯性矩阵示例,以输液泵的阻塞报警需求为例:

需求 ID 需求描述 安全等级 设计 ID 代码位置 测试用例 ID 测试结果 缺陷 ID
SRS-001 阻塞报警响应时间 ≤ 3 s B DES-012 alarm.c: check_occlusion() TC-101 通过 —
SRS-002 报警声压级 45~85 dB(A) B DES-013 alarm.c: set_buzzer() TC-102 通过 —
SRS-003 阻塞解除后 5 s 内停止报警 B DES-014 alarm.c: clear_alarm() TC-103 失败 BUG-007
SRS-004 报警状态可被护士确认并静音 60 s C DES-015 ui.c: mute_alarm() TC-104 通过 —

表中 BUG-007 表示 TC-103 失败,对应 SRS-003 未满足。修复后需要重新执行 TC-103,并更新测试结果和缺陷状态。TM 不是一次性文档,而是随每次需求变更、代码修改和测试执行持续更新的活文档。在医疗软件审计中,TM 的完整性和一致性是重点检查项:任何一条需求如果没有对应的测试用例,或任何一个测试用例无法追溯到需求,都是追溯断链,必须补齐。

建立 TM 时,建议先冻结需求 ID 命名规则,再让设计、代码、测试各自引用同一套 ID。这样即使工具更换,追溯关系也不会丢失。对于安全等级 A 的软件,追溯粒度应细到函数级;B 级可到模块级;C 级可到功能级。

把测试嵌入生命周期,本质上是把“验证证据”的生产提前并分散到每个阶段。V 模型提供层级对应关系,敏捷和迭代提供快速反馈循环,而入口/出口准则和可追溯性矩阵则提供可审计的判定依据。三者结合,才能让医疗嵌入式软件的测试既高效又合规。