自动化测试
我用AI写测试代码——六套Prompt模板从单元到全链路
文章目录
一、写测试代码的痛点不是思路,是写法
1.1 问题在哪
测试的"测什么"你很清楚——正常输入、边界值、异常分支。但具体代码怎么写——该用 @Mock 还是 @MockBean,该 when() 完怎么 verify(),Page Object该怎么组织——这些是每次写都重新翻文档的东西。
1.2 我的做法
自从用了 AI 辅助编码,我把这些重复的"写法"抽成了Prompt模板。告诉AI要测什么、用什么框架、覆盖哪些场景——AI生成测试骨架,我补充业务逻辑。
这些Prompt是实际操作中验证过的,覆盖了从后端单元测试到端到端测试的完整链路。
1.3 六套模板总览
| 序号 | 模板 | 覆盖层次 | 框架 |
|---|---|---|---|
| 1 | 后端单元测试 | Service/Controller | JUnit 5 + Mockito |
| 2 | API接口测试 | REST接口 | Playwright / RestAssured |
| 3 | 端到端测试 | 页面操作 | Playwright |
| 4 | 全链路一键测试 | 全部串起来 | Shell脚本 |
💡 下面逐个展开,每个模板包含:Prompt原文 + 生成代码示例 + 关键约定说明。
二、后端单元测试 —— 每个方法至少三种覆盖
2.1 Prompt模板
为 [模块名/类名] 写 JUnit 单元测试,覆盖:
- 正常输入/边界值/异常输入
- 数据库操作的事务回滚
- null 安全的防御性编程
- 并发/重入安全性(如有)
技术约定:
- 框架: JUnit 5 + Mockito
- 数据库层: MyBatis mapper 用 H2 内存库或 Mock
- Controller: MockMvc 测试 HTTP 层
- Service: Mock 下层依赖,测业务逻辑
- 文件位置: src/test/java/[包路径]/[类名]Test.java
- 运行: mvn test -pl [模块名] -Dtest=[类名]Test
要求每个方法至少覆盖:
- happy path(正常流程)
- null/empty 输入
- 异常分支的错误码/错误类型验证
2.2 生成的测试代码
@ExtendWith(MockitoExtension.class)
class XxxServiceTest {
@Mock
private XxxMapper mapper;
@InjectMocks
private XxxService service;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
@DisplayName("正常创建返回ID")
void create_shouldReturnId() {
when(mapper.insert(any())).thenReturn(1);
String id = service.create(new XxxDto());
assertNotNull(id);
}
@Test
@DisplayName("空参数应抛异常")
void create_nullParam_shouldThrow() {
assertThrows(IllegalArgumentException.class, () -> service.create(null));
}
}
2.3 关键约定说明
核心不是生成代码本身——是Prompt约定了覆盖范围。AI可能会遗漏边界值测试,但你在Prompt里写了 null/empty 输入,它就一定会生成对应的测试方法。
下表对比了"有约定"和"没约定"时AI生成的差异:
| 约定项 | 不写 | 写了 |
|---|---|---|
| null输入测试 | 大概率遗漏 | 每个方法都有 |
| 异常分支测试 | 只生成happy path | 覆盖IllegalArgumentException等 |
| 技术框架 | 可能用JUnit 4 | 严格JUnit 5 + Mockito |
| 文件位置 | 随便放 | 按Maven标准目录 |
三、API接口测试 —— 正常、鉴权、异常三块
3.1 Prompt模板
测试 [模块/控制器] 的所有 REST 接口:
正常场景:
- 请求/响应格式正确(状态码、JSON 结构、字段类型)
- 增删改查完整生命周期:创建 → 查询 → 更新 → 删除 → 确认
- 分页参数的正确行为
鉴权场景:
- 有效 token → 200
- 无 token → 401
- 过期/篡改 token → 401
- 无权限 token → 403
异常场景:
- 必填字段缺失 → 400
- 非法数据类型 → 400
- 不存在的资源 ID → 404
- 重复创建 → 409
- 内部异常 → 500(不泄露敏感信息)
技术约定:
- 框架: Playwright API test 或 JUnit + RestAssured
- 鉴权: 先调登录接口获取 token
- 数据清理: 测试后删除测试数据
- 运行: npx playwright test --reporter=list
3.2 三个测试块的覆盖矩阵
API接口测试的核心是三块覆盖缺一不可:
| 测试块 | 覆盖场景 | 验证重点 |
|---|---|---|
| 正常场景 | CRUD完整生命周期 + 分页 | 状态码、JSON结构、字段类型 |
| 鉴权场景 | 4种token状态 | 200/401/403响应码 |
| 异常场景 | 5种错误输入 | 400/404/409/500响应码 |
3.3 关键约定说明
这里最核心的是鉴权场景的约定——不告诉AI的话,它只会测正常返回。401/403的测试需要在Prompt里显式要求。
很多团队的API测试只覆盖了"正常场景"这一块,鉴权和异常完全没测。线上出问题往往就是这两块的漏洞。
四、Playwright端到端测试 —— 模拟真实用户操作
4.1 Prompt模板
用 Playwright 对 [功能/页面] 做端到端测试:
测试场景:
1. 正常流程:[用户操作的完整步骤]
2. 边界:空数据 / 最大值 / 特殊字符
3. 异常:网络断开 / token 过期跳登录 / 后端错误时的 UI 提示
断言清单:
- UI 元素可见性、文本内容
- 操作后 API 返回正确
- 表单提交后数据库持久化
- 页面无 console.error
- 加载态和空态的正确展示
技术约定:
- 框架: Playwright (chromium)
- 配置: baseURL, timeout, screenshot='only-on-failure'
- 鉴权: fixture/beforeEach 中登录
- 文件: e2e/{功能名}.spec.ts
4.2 生成的代码骨架
import { test, expect } from '@playwright/test'
test.describe('功能模块', () => {
test('操作流程', async ({ authedPage: page }) => {
await page.goto('/path')
await page.waitForLoadState('networkidle')
await page.locator('button.action').click()
await expect(page.locator('.result')).toBeVisible()
})
})
4.3 E2E测试的断言层级
端到端测试不只是"点按钮看结果",需要在多个层级做断言:
| 层级 | 断言内容 | 示例 |
|---|---|---|
| UI层 | 元素可见性、文本内容 | expect(locator).toBeVisible() |
| 网络层 | API返回正确 | expect(response.status()).toBe(200) |
| 数据层 | 数据库持久化 | 查库验证数据已写入 |
| 体验层 | 加载态、空态、错误提示 | 骨架屏显示 → 数据加载完成 |
| 质量层 | 无console.error | page.on('console', ...) |
五、全链路一键测试Prompt
5.1 Prompt模板
对 [项目名] 执行全链路测试:
1. 后端单元: mvn test -pl [模块名]
2. 前端单元: npx vitest run
3. API 集成: npx playwright test e2e/api-*.spec.ts
4. E2E: npx playwright test e2e/pages-*.spec.ts
要求:
- 全部通过后输出汇总:通过/失败/跳过数量
- 失败项输出:测试名 + 断言差异 + 修复建议
5.2 四层测试的执行顺序
这个Prompt不是为了生成代码——是让AI帮你跑测试并汇总结果。四层测试按依赖关系从底层往上执行:
| 执行顺序 | 测试层 | 命令 | 失败时说明 |
|---|---|---|---|
| 1 | 后端单元 | mvn test -pl [模块名] |
Service/Mapper逻辑错误 |
| 2 | 前端单元 | npx vitest run |
组件/工具函数错误 |
| 3 | API集成 | npx playwright test e2e/api-*.spec.ts |
接口契约或鉴权问题 |
| 4 | E2E端到端 | npx playwright test e2e/pages-*.spec.ts |
用户流程走不通 |
💡 底层测试失败了,上层不用跑——先修Service再测API。
失败了直接告诉你是哪个测试、差了什么、可能怎么修。
六、这些Prompt为什么有效
6.1 通用Prompt vs 约定Prompt的对比
通用的测试Prompt(“帮我写测试”)效果很差,因为AI不知道你的技术栈、不知道你的覆盖标准、不知道你的运行方式。
| 对比项 | “帮我写测试” | 约定式Prompt |
|---|---|---|
| 技术框架 | 可能用JUnit 4或TestNG | 严格JUnit 5 + Mockito |
| 覆盖范围 | 只有happy path | happy path + null + 异常 |
| 文件位置 | 随意 | Maven标准目录 |
| 能否直接跑 | 不能,要改import | 能,直接mvn test |
6.2 四条约定是核心
这些Prompt有效的关键在于把约定写在了前头:
- 技术栈约定:JUnit 5 还是 JUnit 4、Mockito 还是 MockBean、Playwright 还是 Cypress
- 覆盖标准约定:每个方法至少 happy path + null + 异常三种
- 文件位置约定:测试文件和源文件的相对路径关系
- 运行命令约定:
mvn test -pl xxx还是npx vitest run
这四条约定了,AI生成的代码就是可用的——跑得起来、放在正确的目录、覆盖了应该覆盖的场景。剩下的业务断言逻辑需要人补,但骨架不需要重写了。
6.3 一句话总结Prompt技巧
好的Prompt不是万能咒语,是把不确定的东西确定化——告诉AI"按这个规则、在这个位置、用这个命令运行"。约束越具体,生成结果越接近可用。
七、总结
7.1 AI写测试的价值定位
AI写测试代码的价值不是"全自动生成"——是省掉重复的骨架代码。每个Service的测试都要写 @Mock、@InjectMocks、@BeforeEach 的初始化,每个Controller的测试都要写 MockMvc 的 perform().andExpect()。这些Prompt把骨架交给了AI,人只负责填充业务断言。
7.2 四套模板速查
| 模板 | 适用场景 | 一句话要点 |
|---|---|---|
| 后端单元测试 | Service/Controller | 约定覆盖三种:正常/null/异常 |
| API接口测试 | REST接口 | 三块缺一不可:正常/鉴权/异常 |
| 端到端测试 | 页面操作 | 五层断言:UI/网络/数据/体验/质量 |
| 全链路一键 | 提测前 | 底层往上执行,失败即停 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)