夜雨聆风学习资料网

ARTICLE · 1067995

自动化 02|验证 AI 产出的代码与工具:从双编程到单元测试

自动化 02|验证 AI 产出的代码与工具:从双编程到单元测试

摘要

AI 生成代码已经是不可逆的趋势,随之而来的问题是:该怎么检验 AI 的产出?日常工作中的检验大致分两层——工具开发与项目递交,本篇聚焦前者,梳理传统的验证流程,再补上 AI 时代该有的那一块,算是抛砖引玉。这个系列后续两篇会深入 SAS 宏的单元测试与回归测试的思路。

本文仅代表个人想法与见解,技术细节均以原文为准。若你对原文的理解与我不同,或发现哪里写得不对,欢迎通过公众号后台留言或私信指正。Peer‑review comments are welcome.

首次发布:2026-09-24

一、背景

AI 进入临床统计领域已是大势所趋。随之而来的现实问题是:AI 输出的代码,应当如何检验?

本行业与互联网行业的底层逻辑有着根本差异。互联网那套"快速上线、AI review、线上再修缺陷"的模式,搬到药物研发里基本行不通——受监管要求和错误成本两重约束,我们没法拿生产环境去试错。何况合规本身就有明文要求:ICH E6(R3) 在原则部分指出,参与试验的人员应"通过教育、培训与经验取得相应资质"(Principle 5.1,p.5),而临床试验所用的计算机化系统应"fit for purpose(例如适当时通过基于风险的验证)"(Principle 9.3,p.6)。

由此引申:当代码由 AI 产出时,从业者需要具备验证其输出的能力,正是这两条原则在 AI 场景下的自然延伸。需要说明的是,这是笔者的推演而非指南的明文——E6(R3) 全文并未提及 artificial intelligence 或 machine learning,仅在个别条款中出现 automated 一词。

从检验对象来看,AI 生成的代码大致可分为两层:

  • 一是项目层面递交的代码,即围绕具体研究与递交物(delivery)产生的程序及其配套检查;
  • 二是工具开发层面的代码,即 SAS 宏、R 函数 / R 包、Python 脚本一类用于辅助处理的小工具。

本篇聚焦于后者,即工具层面。

工具层面的验证,如今已有不少成熟的工程框架可倚仗。头部药企用 R 开发包时,基本都会引入 testthat 一类单元测试框架。反观 SAS 宏这头,公开讨论明显少得多——如何给它写测试、又该怎么验证,行业里可参照的经验并不充分。这正是本文想梳理清楚的:如果产出的是一个 SAS 宏,测试究竟该怎么做?

下文先以 PharmaSUG China 2023 的 CC-106 为例,说明传统的工具验证流程;再结合 AI 时代的场景作补充;最后聚焦功能测试这一步,引出单元测试这一思路。

二、传统上是怎么验证的,AI 时代要补什么

行业既有的做法,可以以 CC-106 为代表。该文提出以软件开发生命周期(SDLC)来开发统计编程工具,主要面向 SAS 宏,整体流程为需求分析与设计、开发、测试与验证、部署。其中的"测试与验证"(Testing and Validation)阶段,给出了四个步骤:

  1. 审阅源代码与用户手册;
  2. 测试报错信息与返回码;
  3. 测试功能(functionality);
  4. 测试极端值(extreme values)。

Code Review:在 AI 时代权重更高

第一步是审阅源代码与用户手册。这一步原本就存在,但当代码由 AI 生成时,重要性进一步上升——需要确认产出是否真正满足 SAP(Statistical Analysis Plan,统计分析计划)中的业务需求。

所以早在给 AI 下 prompt 的阶段就得埋好伏笔:每段代码负责什么,注释要写全,可读性也要顾上,方便后面审。更关键的是,我认为审阅者自己得有基本的语法判断力,而不是只会 vibe coding。这是进 review 的前提,也是最低要求——AI 写的代码,这一步同样绕不过去。

其余三步

测试报错信息与返回代码。工具被误用时,是否返回了足够的信息以引导用户正确使用。典型情形包括:必填参数未指定、参数值非法、输入数据集不存在、数据集存在但缺少必需变量、输出路径不存在等(避免"酒吧点炒饭"——用户给了一个你压根没设想过的输入)。若工具只是中止执行却不给提示,使用者很难定位问题。

测试功能。在正确使用的前提下确认输出正确。CC-106 建议使用真实的 III 期研究数据,并通常以双编程(double programming)进行校验。

测试极端值。构造含极端值的 dummy data,确认工具在边界条件下依然稳定。这一步对 AI 场景尤为重要——AI 对指令的理解未必覆盖到各类边界条件,需要专门加以检验。

角色与版本控制

流程之外,CC-106 还明确了三方角色:Requester 审阅并批准验证方案;Tester 按方案执行,记录 "Actual Outcome" 并截图留证;QA 复核执行结果,给出通过与否的结论。全部通过后形成 Validation Report,整套文档进入 QA 系统留档。

版本控制方面,每个 SAS 宏带有版本号,如 %m_xxx_v1;向后兼容、不影响调用方程序的小改动(如缺陷修复、宏元数据更新),通常不升版本号。

模型视角:上述原文均未涉及 AI。结合 AI 场景可补充两点——其一,AI 可用于生成测试用例与 dummy data,但其产出仍需经过同一道验证闸门,不因来源为 AI 而免检;其二,AI 一天可产出多个工具,验证产能反而更紧张,这也使得流程化的验证方法更值得被重新审视。

三、功能测试这一步,不止双编程

CC-106 第三步给出的方案是"真实数据 + 双编程"。这一步值得进一步讨论。

双编程的局限在于,它只验证了临床数据库当前状态下的输出。一旦数据库更新、新数据进入,此前通过验证的程序可能在未曾见过的数据点上出错(AD09, p.1)。对于仅在单个研究中使用一次的程序,影响相对有限;但对于跨多个研究复用的共享宏,问题就很突出——无法保证其后续遇到的数据形态。

因此在功能测试这一步,可以引入单元测试(Unit Testing):以一组已知输入运行最小的代码单元,再将实际输出与预先定义的预期结果进行比对。

需要说明的是,单元测试、回归测试这套东西并非本行业原生,它们原本属于软件工程——Java 的 JUnit、C# 的 NUnit 一类框架早在二十多年前就普及了。AD09 的作者也直言,单元测试框架这个概念"far from novel"(AD09, p.2)。我们行业长久以来偏重双编程、稽查与 QC 抽样,方法论上相对朴素。但到了 AI 时代,工具产出速度陡增、改动频繁,把这些软件工程的成熟实践搬过来,反而变得前所未有地重要。尤其是回归测试(Regression Testing):每次改动后自动重跑既有测试,防止修了 Bug 又引入 Bug(AD09, p.1)。

PharmaSUG 2013 的 AD09 在摘要中即指出:对于跨多个研究使用的共享宏,单元测试往往比双编程更为合适。SAS 社区亦有可用框架,FUTS 与 SASUnit 均为免费方案(AD09, p.2);需要注意的是,公司 SOP 可能要求对所有安装的第三方软件先行验证(AD09, p.2),这是落地时的现实门槛。

回到工具层面的框架差异:头部药企以 R 开发包时可直接使用 testthat 完成单元测试,而 SAS 宏一侧长期以双编程为主。将单元测试的思路迁移到 SAS 宏,正是值得参考的方向。

四、关于项目层面的验证

这是我最近看到同行的一篇文章,是在项目层面采用了单元测试:说明已经有同行把单元测试从工具层往前推了一步,直接用在递交项目的程序验证上。这其实印证了本文的判断——当代码产出速度被 AI 拉高之后,验证方法向工程化演进就不再是可选项,而是迟早会发生的事。项目层的验证同样受篇幅所限,这里只作提示,留待后续系列展开。

数据保密下,AI 改 SAS 代码怎么保证正确性?——用单元测试破解验证难题

五、下一篇预告

下一篇将聚焦 AD09 这篇文章本身:说明它如何将测试结果写入 SAS log,以及 driver 程序如何读取 log 并汇总生成报告。这套框架具有参考价值。有兴趣可先行阅读该文的 "ANATOMY OF A TEST PROGRAM" 与 "GLUING THE FRAMEWORK TOGETHER" 两节。

Reference

Yan, Q. (2023). Software development life cycle in developing statistical programming tools. PharmaSUG China 2023, Paper CC-106.

Nizol, M. (2013). A simple approach to the automated unit testing of clinical SAS macros. PharmaSUG 2013, Paper AD09. https://www.pharmasug.org/proceedings/2013/AD/PharmaSUG-2013-AD09.pdf(本文引用页码均指该 PDF 自身页码。)

ICH. (2025). ICH E6(R3) Guideline for Good Clinical Practice. 国家药品监督管理局药品审评中心(CDE)ICH 专栏. https://www.cde.org.cn/ichWeb/news/getNewsDetail/2/9823c23088ca971d2fdc3506be75210c/0(p.5、p.6 为指南正文页码。)

Appendix

  • SAS:统计分析系统(Statistical Analysis System)。
  • SDLC:软件开发生命周期(Software Development Life Cycle)。
  • SAP:统计分析计划(Statistical Analysis Plan),编程需求的源头。
  • TLF:表格、清单、图形(Tables, Listings, Figures)。
  • SDTM / ADaM:CDISC 标准数据集(原始数据 → 分析数据)。
  • 双编程(Double Programming):两人按同一 spec 各写一份互验。
  • 单元测试(Unit Testing):用已知输入跑最小代码单元,比对预期输出。
  • 回归测试(Regression Testing):改动后重跑测试,防止引入新 bug。
  • FUTS / SASUnit:SAS 社区的免费单元测试框架。
  • ICH E6(R3):药物临床试验质量管理规范(GCP)现行版本。
  • Validation Protocol:验证方案;Tester / QA / Requester:执行 / 质控 / 申请三角色。

相关学习资料