大模型生成单元测试是目前比较常见的研发侧落地的应用场景之一。为了对大模型以及单测生成方案进行评估,因此梳理了一个评估方案,供业内同仁参考。
此处所谓的单测生成是指基于既有的代码,让大模型来自动生成单元测试。生成成功的标志是:
1) 可以生成单元测试用例
2) 该用例可以被编译、执行通过
3) 被测方法被调用
4) 有断言
评估框架
类别 | 具体项 |
---|---|
代码场景 | 对各种代码场景的覆盖 |
过程 | 用例的通过率和正确率% |
结果 | 断言丰富度和数量 |
Mock丰富度 | |
覆盖率(行覆盖/分支覆盖)% | |
1. 人工评判 | |
用例体验 | 代码可读性 |
经济性 | 成本(非私有化部署需要考虑) |
生成耗时 |
代码场景
基于我们现有的方案,经过测试ChatGPT3.5以及GLM4这两个大模型,发现17个通用场景大概能通关12-14个,以及SpringBoot项目中的前4个场景。可以说基本能满足了。因此目前已经将单测生成的插件在内部进行试点使用。当然,由于内部部署的模型规模要小很多,生成效果会进一步打折。
通用场景:
·基础代码场景 (10行以内的一个方法,无任何外部代码调用)
·基本if-else逻辑
·方法间调用-本类其它方法(public)
·方法间调用-本类其它方法(非public)
·方法间调用-非本类的方法
·静态方法调用- 项目自定义Utils
·静态方法调用-SDK类,如定时器
·静态方法调用-枚举类
·接口/实现的调用
·抽象类/实体类的继承
·异常(受检异常、非受检异常、try-catch-finally)
·文件I/O操作
·反射代码
·泛型
·lambda
·圈复杂度高
·方法体超长
Springboot项目场景
·Mybatis数据库交互-查询后插入(upsert操作)
·Mybatis数据库交互-插入数据库后return Id(期待使用 Mockito对数据库自增Id进行模拟)
·Mybatis数据库交互-从第三方获取Id,随后插入数据库中,返回值代表成功失败(期待使用 Mockito Capture验证中间过程值而不是只验证返回值)
·@Autowired引入Service,调用Service中方法
·applicationContext.getBean注入bean,调用bean中的方法,期待使用MockStatic进行mock
单元测试用例筛选(Selection)
单测用例如果能自动生成,用例编写的成本就会极大降低,转而会对用例的维护带来压力。因此,有必要考虑单测用例筛选的问题。目前这部分工作还没有启动,以下是一些思路。
筛选条件 | 方案 | |
---|---|---|
1 | 缺陷对应的测试用例优先保留 | 测试用例的方法上带有 @Bug 或者 @OnlineBug 的注解 |
2 | 接口覆盖率100%,应保留接口自动化覆盖的用例 | 每个接口至少要保留一个单接口的集成测试用例 |
3 | 最少用例实现最大覆盖率(行覆盖、分支覆盖、判定?jacoco貌似没有) | 剔除没有新增覆盖率的用例。案例:某个用例执行之后,整个用例集的覆盖率并没有新增。(可能受用例执行顺序的影响,每次筛选的结果会不一样) |
4 | 用例集的执行耗时最小 | 在3的基础上,如果有多个用例可选,则选择耗时最短的(要考虑 setup/teardown) |
方案局限性
就代码生成单测,属于后补用例的一种,只是将后补用例的成本极大降低了而已,但是并没有完全解决Test Oracle的问题,也就是说用例虽然生成了,但也可能是假阴性( False Positive)的。
希望大家注意。