【中】使用AI生成Java单元测试
一、开始
最近公司要求使用Ai提效,我这边的一个主题是使用AI生成Java单元测试。从结果来看,要比预期好很多,最开始的目标是在写单元测试的效率提升 30%,从结果来看是要大于这个预期的。
从结果来看就是 Cursor + 提示词,生成单元测试,如果想直接看结果可以直接跳到【四、使用Cursor】,如果想要看看对比,可以一步步往下看。
整体的调研思路:
- 选一些大模型使用对话体和IDEA插件对比
- 插件内部进行对比
- 优化提示词,生成想要的效果
二、对话体和插件对比
2-1、测试的标准
- 生成的单元测试需要修改多少才可以正常执行
- 单元测试覆盖场景是否全面
- 操作的便捷性
注:
- 为了通用,所有测试流程都是一样:先给提示词,再给需要生成测试的代码
- 不会二次提问,直接基于第一次给出的单测进行校验
5分的定义:(不可能有5分的,哈哈)
- 输出没有任何的编译错误 (导包不算)
- 单测全部执行成功
- 和我想的测试场景几乎一致
2-2、模型对比
模型名称/地址 | 开发团队 | 评分(满分5) |
---|---|---|
文心一言 | 百度 | 3.5 |
GPT-4o/4o-with-canvas | OpenAI | 3 |
通义千问 | 阿里 | 3 |
kimi | 月之暗面科技 | 2.5 |
讯飞星火 | 科大讯飞 | 2 |
2-3、插件对比
插件名称 | 开发团队 | 评分(满分5) |
---|---|---|
GitHub Copilot | Github | 3.5 |
CodeGPT | 3.5 | |
通义灵码 | 阿里 | 3 |
百度Comate | 百度 | 2.5 |
CodeGeeX | 智谱清言 | 1 |
iflycode | 科大讯飞 | 1 |
ChatGPT Bito AI Code Assistant | Bito | 0.5 |
MarsCode | 字节 | 0.5 |
单元测试的非常依赖上下文,几乎无法直接使用对话体的模型来生成,这需要整理很长的上下文。
理想的状态还是在IDEA插件中,支持提示词(这样就可以自定义一些规范)。
三、插件内部对比
前端给我推荐了 Cursor,抱着试试的心态,结果出乎意料的好。下面是 Cursor 和一些比较好的插件详细对比。
对比维度 | Cursor | CodeGPT | 通义灵码 | Comate | Copilot |
---|---|---|---|---|---|
插件简介 | 基于vscode二开的AI编辑器 | 开源的IDEA插件,可以对接多种大模型 | 阿里开发的AI编码插件 | 百度开发的AI编码插件 | GitHub开发的AI编码插件 |
生成质量(5分最高) | 4分 1. 非常理解上下文 2. 非常理解提示词 3. 场景很全面 | 3分 1. 可以理解提示词,生成的结果会更加规范一些 2. 覆盖场景相对Copilot和通义会差一点,但比Comate好 | 3分 1. 不理解提示词 2. 覆盖的场景很全面 3. 要改的相对Copilot多一点 | 2.5分 1. 不理解提示词 2. 覆盖的场景比其它三个要少 | 3.5分 1. 可以理解提示词,但不是所有的规范都遵循 2. 覆盖的场景比其它的全面,生成的代码错误相对较少 |
操作流程(5分最高) | 4分 1. 内置提示词(一次配置就好) 2. 无脑 @Codebase+给出要生成的方法名 3. 确定AI生成的内容(确定后会自动创建或写入文件) 4. 切换到IDEA开始修改或执行 | 2.5分 1. 内置提示词(一次配置就好) 2. 使用@选中文件 3. 给出需要生成的单元测试方法 4. 复制生成好的代码 5. 修改或执行代码 | 3分 1. 选中代码块右键直接生成 2. 复制生成好的代码 3. 修改或执行代码 也可以打开对话框,在对话框输入提示词,选中文件,再给出需要生成的单元测试方法。(但效果并不是很好) | 3分 1. 选中代码块右键直接生成 2. 复制生成好的代码 3. 修改或执行代码 也可以打开对话框,在对话框里面选择【知识】,再选择 【文件】,再给出需要生成的单元测试方法。(但效果并不是很好) | 1.5分 1. 打开对话框,输入提示词 2. 选中相关的文件 3. 给出需要生成的单元测试方法 4. 复制生成好的代码 5. 修改或执行代码 |
是否支持集成测试 | 支持的很好,都可以从别的单元测试里面拿到数据库的id | 支持 | 生成的测试不是很好,会出现方法模拟错误和参数错误的情况 | 需要每次都先给样例模板才可以生成集成测试,生成的结果会有很多无用的代码 | 支持 |
生成速度 | 快 | 快 | 很快 | 很快 | 不太稳定,有时候快,有时候慢 |
扩展性 | 1. 支持编辑器提示词 2. 支持单个项目提示词 | 内置提示词 | 1. 无法内置提示词 2. 对话框输入提示词理解不好 | 1. 无法内置提示词 2. 对话框输入提示词理解不好 | 可以理解提示词,需要每次对话都要先发一遍 |
成本/费用 | 20$/月 但可以一直注册账号、或用插件薅羊毛 | 想要正常使用都必须要买 API key eg:通义的 模型调用-输入¥0.0035/千个 模型调用-输出¥0.007/千个 注:百度的模型暂时用不了,CodeGPT的模板无法适应百度的API | 免费 | 免费 | 1. 需要购买账号 2. 需要梯子 |
优缺点 | 优点: 1. 内置提示词 2. 生成的单元测试质量好 3. 不用复制粘贴,代码直接写入文件,也不用导包 4. 比较好的追加沟通,且可以把执行错误发给它,然后它会继续修改,效果还不错 缺点: 1. 付费(目前可不断薅羊毛) 2. 需要开2个编辑器 3. 学习一个新的编辑器成本 | 优点: 1. 内置提示词 2. 相对稳定,输入是很确定的(本质是调API,不会对你输入做处理) 缺点: 1. 付费 2. 交互和生成的质量不如cursor | 优点: 1. 免费 2. 操作简单(右键生成) 缺点: 1. 无法理解提示词 2. 右键直接生成不稳定 3. 质量和交互一般 | 优点: 1. 免费 2. 操作简单(右键生成) 缺点: 1. 无法理解提示词 2. 右键直接生成不稳定 3. 生成的质量最差 | 优点: 1. 可以理解提示词(需要每次输入) 2. 生成的测试质量相对很好 缺点: 1. 付费,需要梯子 2. 提示词需要每次都输入(能理解但理解的不是很全面) 3. 交互和生成的质量不如cursor |
四、使用Cursor
4-1、Cursor初体验
选择Cursor的理由如下:
- 生成的单元测试质量高(它可以很好的理解整个代码库)
- 内置提示词,拓展性好(提示词的使用方式有很多种,下面会展示)
- 追加提问,可反复修改代码(比如生成的代码有问题,把异常告诉它问题,它会对出问题的地方修改)
- 操作便利,生成的结果只需要点一下 Accept 就会自动创建或写入,不管是首次还是多次生成都可以
1、安装 Cursor
直接去官网下载: https://www.cursor.com , 交互什么的和vscode一样(毕竟是基于vscode二开的)
导入Java项目,会提示安装一些Java扩展。下面是一些基本的插件(按照提示就会安装,MybatisX看个人需求)
- Extension Pack for Java
- Debugger for Java
- Language Support for Java(TM) by Red Hat
- Maven for Java
- Project Manager for Java
- Test Runner for Java
- IntelliJ IDEA Keybindings 保证大部分快捷键和IDEA一样
- MybatisX 可以在Mapper的接口和XML之间跳转
2、注册Cursor账号
注册完登陆,就可以看到免费试用的权益 https://www.cursor.com/settings

3、CHAT和COMPOSER
chat和composer 是Cursor 和Ai对话的两种形式
- chat就和普通的IDEA插件一样,提供对话模式的交互
- composer和chat最大的区别是它有写文件的权限,当你认为它写的代码不错,就可以让它帮你一键写入
每一次对话,就会扣减上面 250次中的一次(对话框的左下角可以选择模型,有的模型是不限量的) 额度用完了可以使用插件破解:https://mp.weixin.qq.com/s/oQuLXpUzSdBe1LwlQCPjTw

注:composer 除了从右边打开,还有一种用法是直接选中代码,快捷键会弹出一个聊天窗,对于一些代码块的修改会方便很多

4、小细节
1、Cursor默认的文件结构是一层一层的,和IDEA有点区别。通过设置可以让目录结构和IDEA一样

2、默认的主题颜色可能对大部分人来说太绚丽了,有些刺眼,可以在这里选择适合自己的主题颜色

5、启动SpringBoot项目

6、导入提示词
Cursor对于提示词的配置有多种方式
- docs:基于在线文档的提示词,可创建多个,在对话框中提问的时候可以 @选择一个
- notepads:本地的提示词,可创建多个,在对话框中提问的时候可以 @选择一个
- .cursorrules: 当前项目的提示词,在每个项目的根目录下创建这样一个文件
- Rules for AI: 整个编辑器的提示词,Cursor Settings > General > Rules for AI
4-2、生成单元测试
单元测试生成有两种形式:
- 对整个文件的 @Override 方法生成测试,用于补全历史的单元测试
- 对某个文件的某个方法生成测试,用于新方法生成测试
1、对新方法生成单元测试 (常用的方式)
- 打开一个新的 composer 窗口
- @Docs + @Codebase + @Files + 要生成单元测试的方法
- 检查生成的结果,没问题就 Accept (也可以直接先Accept再去编辑器里面看)

2、对整个类生成单元测试
- 打开一个新的 composer 窗口
- @Docs + @Codebase + @Files
- 直接先Accept再去编辑器里面看

3、对代码调试
对于各种IDEA插件生成的单元测试来说,几乎就只有手动调试一种方式,主要原因它们对整个代码库理解不是很好,很难对给出的异常做太多的优化
Cursor可以通过反复的对话来修正之前生成的代码
3-1、调试的编辑器
装完上面那些Java扩展插件之后,Cursor一样可以执行单元测试,直接在Cursor里面调试是没有任何问题的

Cursor毕竟是个新东西,刚开始大家可能不太习惯,或对于一些复杂的单元测试不好处理的时候。我们可以切换到IDEA里面去调试,文件是早已生成好了的
3-2、调试步骤
对于生成的单元测试无法正常执行的时候,调试过程如下
1、语法错误(极少会这样),把鼠标放上去点击 Fix in Composer

2、把运行的异常直接发给composer
简单描述:xxx 方法执行报错: 全部异常
3、对于复杂的代码,通过异常AI无法解决的,需要给它一些提示
- 可以告诉它,是哪几行代码运行异常
- 可以复制代码报错的原因,比如报错事因为有部分代码没有Mock,就可以复制没有Mock的这部分代码给它
- 断言不对,可以复制断言的代码,告诉它现在的预期不对

4、到这里大部分问题就都被解决了,如果还是不行,大概是要手动调试了
五、提示词获取
关注微信公众:小道仙97 ,回复:Java笔记, 获取密码