乐于分享
好东西不私藏

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

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

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

临床试验里,ADLB、ADSL 这类含真实个体数据的数据集是高度保密的,很多公司是明令禁止 AI 直接读取的。那还能不能让AI agent帮我们改代码、自己测代码?如何不触碰红线的前提下愉快地vibe coding呢?这篇文章分享一个在我们团队里验证过的方法。

01一、一个真实的困境

做临床统计的同事应该都有体会:SAS 程序(SDTM、ADaM)改动之后,最怕的就是"跑一遍全量,结果对不对、日志干不干净"。

现在大家都在用 AI 帮忙改代码。AI 很会改,但有个尴尬的地方——它读不到你的真实数据。

为什么?因为 ADLB、ADSL 这类数据集里是真实的受试者个体数据,涉及隐私和保密,很多公司出于合规明确禁止把这类数据交给 AI。于是出现了一个悖论:

•你希望 AI 帮你把代码改对、改稳;
•但 AI 看不到真实数据,就没法验证改完稳不稳;
•最后还得靠你自己在正式环境里跑一遍全量,发现问题再回头改。

一来一回,效率并没有真正提上去。

02二、换个思路:不跑全量,先跑"单元测试"

解决这个悖论,关键是想清楚一件事:AI 改的往往只是代码里的一小块逻辑,而不是整个流程。

比如某次我们要修改某个衍生指标的分级判定规则。真正改动的,就是数据步里的一个分支:怎么取值、怎么算、怎么分级。至于上游读库、下游落盘,AI 一行没动。

既然只动了一小块,那我们就只测这一小块——这就是单元测试的思路。

具体做法分四步:

第一步:把改动逻辑"抽"出来。在测试程序里,用 datalines(SAS 造数语句)手工构造一小段最小数据集,只包含这个分支需要用到的变量。比如"有没有检查、检查值、参考上下限、是否正常"。这些是假的、脱敏的数据,随便造,不涉及任何真实个体。

第二步:原样复刻改动逻辑。把正式程序里那一段被改的分支,按原样搬进测试程序。注意是"按原样",保证测的就是线上那份逻辑,而不是重写一份。

第三步:造各种边界情况。这一步是单元测试的灵魂。光测正常情况不够,要把"正常、异常、缺失、未做检查、数值临界"这些组合都造出来。每一次跑,都对应一组明确写好的期望结果。

第四步:连接 SAS 服务器,跑起来。通过一个连接工具(saspy 走 IOM 会话,如果感兴趣的人多,可以单独开一期文章,欢迎讨论)把测试程序提交到 SAS 服务器执行,收回日志(LOG)和结果(LISTING),再自动比对期望结果,并扫描日志里有没有 ERROR、WARNING、异常 NOTE。

03三、单元测试漏掉的那个组合

说个我们实际遇到的例子(细节已脱敏)。

我们改完某指标的分级逻辑,单元测试里 7 个场景全部通过,看着挺稳。结果正式环境一跑全量,日志里冒出一条:

NOTE: 缺失值的生成是对缺失值执行操作的结果。

排查后发现,根因是一个"测试数据没覆盖到"的组合:主指标缺失,但同访视的辅助指标是查了的,程序对缺失值做了运算,就触发了这条 NOTE。

当时漏测的,正是下表里第 3 行这种组合:

场景
主指标
辅助指标
触发 NOTE
已覆盖
有值
有值
否
已覆盖
有值
缺失
否
漏测缺失有值是
已覆盖
缺失
缺失
否

补上这一行场景重新跑,NOTE 消失,逻辑验证通过。

这件事恰恰说明了这个方法的定位和价值:

•单元测试不能保证全量运行一定干净——它只是你的第一道防线;
•但它是最快、最安全的一道防线,能把绝大多数逻辑错误挡在正式运行之前;
•而且它完全可以在不接触真实数据的情况下完成,正好破解了"数据保密 + AI 改代码"的矛盾。

04四、给管理者和程序员的两句话

对程序员:把"跑全量"作为最终验证,把"单元测试 + 连 SAS"作为改代码后的第一反应。改一个小分支,先造数、先跑小的,再上全量。日积月累,你会攒下一套可复用的"测试用例库",回归起来特别省心。

对管理者:与其纠结"AI 能不能看真实数据",不如定一条规则——AI 改代码可以,但验证必须走"脱敏造数的单元测试 + 正式环境的全量回归"两级机制。这样既守住数据合规的底线,又能放心地用 AI 提速。

05五、进阶:怎么让 AI 自己"学会"这套单元测试

到这里你可能有个疑问:方法再好,难道每次都要我手把手教 AI 怎么造数、怎么连 SAS、怎么跑?

其实不用。关键是把这套方法整理成 AI 能自动加载的知识(在 Claude、Cursor 等工具里叫 "Skill")。让 AI"知道怎么测",本质是给它三块能力:

能力
解决什么问题
来源
流程纪律
在哪建任务、怎么备份、工作目录怎么组织
task-runner
 skill
连接执行
怎么连 SAS 服务器、提交代码、回收日志
sas-bridge
 skill
测试设计
怎么抽逻辑、造哪些数、边界是什么、怎么断言
test-designer
 skill

前两块通常是现成的(管"在哪跑"和"怎么连")。真正缺的是第三块——测试设计方法论,因为"造什么数据、覆盖哪些边界"最依赖经验,也最容易漏。

第三块 skill 怎么写,AI 才会用

核心是写成 AI 可执行的结构化流程,而不是说明文字。要点:

1触发条件写在开头:修改了 SAS 取值/计算/分级/标记逻辑就自动加载。
2给出可执行步骤:抽逻辑 → 造数 → 连接执行 → 断言 → 记录。
3边界覆盖矩阵写死:正常 / 异常 / 缺失 / 未做 / 临界点,每个都测。
4经验教训固化成硬性要求:比如"必须主动检查跨变量缺失组合"——这正是上次漏测的教训。写进 skill 后,AI 下次就不会再漏。

触发机制:让 AI "自动想起"用这个方法

•描述触发:在 skill 的 description 里写明触发词(如"修改 SAS 衍生逻辑 / 造测试数据 / 连接 SAS 跑测试"),AI 遇到相关任务会自动加载。
•规则强制:在项目规则文件里加一条"凡修改 SAS 程序逻辑,必须先执行单元测试",形成硬约束。

一句话:把测试方法论固化成 skill,是为了让这套流程可复用、不靠临场发挥。

06六、小结

数据保密不该成为"不能用 AI 改代码"的理由。单元测试 + 连接 SAS 服务器,让我们在完全不触碰真实个体数据的前提下,把 AI 改出来的代码测得更稳、更快、更安心,一定程度上,能够在高度监管和保密的临床试验行业,可以安全地释放一些AI agent的能力!

真正保密的,是真实数据;而测试,用的是我们自己造的假数据。

欢迎各位同行交流,批评(能鼓励更好)指正!


相关学习资料