研究想法

Postgeneration Verification Controls

日 · 2026-04-23 · Software Intelligence

最清楚的近期开发布局,是给模型允许产出的内容加上硬约束,并在生成后继续保留验证。这里最具体的三个例子,是用于静态分析聊天的类型化中间层、从现有测试合成的运行时语义检查器,以及把一个可信测试扩展成场景变体并进行修复和验证的仓库测试机器人。

3 个想法

Typed JSON translation layer for natural-language static analysis

静态分析聊天不该再让模型直接写 Joern CPGQL。更好的做法是两步翻译:模型先填一个小型、类型化的 JSON 表单来表达查询意图,然后确定性代码把这个表单映射成最终查询,并在执行前做校验。证据很具体。在一个覆盖 Apache Commons Lang 和 OWASP WebGoat 的 20 任务基准上,基于 schema 的 JSON 设计在所有测试模型上都胜过直接生成查询,Qwen 72B 提高了 15.0 个百分点,Llama 70B 提高了 25.0 个百分点。它也胜过一个 agent 式工具循环,后者每个任务用了大约 8 倍的 token,结果还更差。

做静态分析自然语言入口的团队很熟悉这种操作上的痛点:生成的查询经常能跑通,却回答错了问题;而自由形式的 agent 循环只会增加延迟和失败点,没解决 DSL 正确性。类型化中间层给产品团队一个位置,在任何东西碰到分析引擎之前,先约束允许的查询类型、必填字段和 schema 检查。

验证路径也很直接。拿一批来自安全团队或 AppSec 用户的真实英文分析请求,给最常见的查询家族定义一个窄 JSON schema,再把结果匹配率、执行成功率和 token 成本与直接生成查询做对比。如果工具已经记录了失败或误导性的 CPGQL 生成,这些请求就是合适的起点。

Runtime checker generation from existing integration tests

有不错测试套件的团队,可以把部分测试编译成始终开启的运行时语义检查器,用在生产和预发环境。FlyCatcher 给出了一条具体路径:把现有测试当成预期行为来源,用静态分析加 LLM 合成推断检查器,用 shadow state 记录所需的抽象状态,并在部署前用保留测试验证生成的检查器。

这正好补上了 coding-agent 工作流里的一个空白。生成的代码可能通过本地测试,但在不同负载下还是会违反语义。运行时检查器能覆盖这类不会让程序崩溃、也不会触发普通断言的失败。在四个 Java 系统的 400 个测试上,FlyCatcher 推断出 334 个检查器,其中 300 个经交叉验证被判定正确。它生成正确检查器的数量是 T2C 的 2.6 倍,检测到的 mutant 是 T2C 的 5.2 倍。

最先会用上的,是那些运行有状态 Java 服务、而且沉默失败代价很高的团队,比如消息、复制、会话处理、库存逻辑,或者任何部署后不变式很重要的代码。一个低成本检查方式是,挑一个有高价值集成测试的子系统,先给一小批测试生成检查器,再在预发环境测三件事:生成检查器的验证通过率、额外的 mutant 检测数、运行时开销。论文给出的开销范围是 2.7% 到 40.3%,这说明在大规模推广前,先测这一项是必要的。

Scenario expansion for repository test bots from a single seed test

仓库测试机器人可以走的一条有用路径,是先从一个开发者写的测试开始,把它扩展成一组场景变体,然后把这些测试修到能编译、能通过。TestGeneralizer 给了这套流程一条具体做法。它先推断种子测试背后的场景,再写出带变体点的场景模板,生成这些变体,并用程序分析得到的项目事实把生成测试保持在有效范围内。

成熟仓库里的需求压力很清楚:第一个测试往往只覆盖一个 happy path,其余场景覆盖通常要等到 bug 报告和补丁发布之后才补上。这篇论文直接瞄准了这个缺口。在 12 个 Java 项目、506 个 focal methods 和 1,637 个测试场景上,TestGeneralizer 的基于 mutation 的场景覆盖率比 EvoSuite 高 57.67%,比 gpt-o4-mini 高 37.44%,比 ChatTester 高 31.66%。最有说服力的采用信号来自实地研究:27 个生成测试里有 16 个被维护者接受并合并。

这是一条可以放进 CI,或者放进针对已改动方法的 pull request review 的工作流,前提是这些方法已经有至少一个可信测试。一个低成本试验办法,是只在有新测试或修改测试的文件上运行,每个种子测试只输出两到三个候选变体,并跟踪合并接受率、flaky test 比例和发现的独立 bug 数。这样既能控制审阅负担,也能看清场景扩展到底是在补充有用覆盖,还是只是在增加测试数量。