测试妹子让我写单测,我偷偷用AI一天干完一周的活
公司要求单元测试覆盖率80%,我看着那几千行的屎山组件,眼泪掉下来。手写?写到下个月。测试妹子天天在群里@我:“帅哥,你的单测呢?” 我灵机一动,让AI帮我写。一天后,测试覆盖率91%,0 bug,测试妹子发了条朋友圈:“某前端切图仔突然开窍了。” 我没敢告诉她,那是GPT-5.5的手笔。
前言
写单测这事,比写业务代码还痛苦。业务代码至少能跑,能看到按钮,能点。单测?Mock 一堆,断言一堆,跑起来全红,改到怀疑人生。尤其接手老项目,一个组件几百行,手动补测试?告辞。
但我发现,AI 写单测的水平已经超过大部分初级工程师。你只要给它组件代码,它能给你生成结构清晰的测试用例:渲染测试、交互测试、异步测试、边界测试,甚至能帮你 mock 掉依赖的 API。
今天我就教你用 AI(Copilot / ChatGPT / Cursor)自动生成高质量 Jest + Testing Library 测试,把一周的活压缩到一天。测试妹子开心,我也能准时下班。
一、为什么 AI 写单测比你手写强?
- 不嫌烦:重复的渲染、快照、事件触发,AI 从不喊累。
- 覆盖全:它记得各种边界条件(空数组、null、undefined),你容易漏。
- 速度快:几秒钟生成几十个测试用例,你手打要半天。
- 风格统一:输出固定模板,代码规范。
缺点:生成的测试可能不够精准(比如断言了不重要的属性),需要你微调。但总比从零开始强。
二、实战:用 Cursor + GPT-5.5 给 React 组件生成测试
我们用一个实际的组件:UserProfile,它接收userId,内部 fetch 用户数据,显示 loading、error、和用户信息。
// UserProfile.jsx import { useState, useEffect } from 'react'; import { fetchUser } from './api'; export function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { setLoading(true); fetchUser(userId) .then(setUser) .catch(setError) .finally(() => setLoading(false)); }, [userId]); if (loading) return <div>加载中...</div>; if (error) return <div>出错了:{error.message}</div>; if (!user) return <div>无数据</div>; return ( <div> <h1>{user.name}</h1> <p>{user.email}</p> </div> ); }步骤 1:打开 Cursor,选中组件代码,右键 -> “Generate Tests”
或者在 ChatGPT 里粘贴代码,加上提示词:
请为以下 React 组件生成 Jest + React Testing Library 的单元测试。需要覆盖:初始加载状态、成功获取数据后显示用户信息、请求失败时显示错误信息、loading 结束后的渲染。请 mock 掉
fetchUser这个 API。
步骤 2:AI 生成的测试(稍加整理)
import { render, screen, waitFor } from '@testing-library/react'; import { UserProfile } from './UserProfile'; import { fetchUser } from './api'; // Mock API 模块 jest.mock('./api', () => ({ fetchUser: jest.fn(), })); describe('UserProfile', () => { beforeEach(() => { jest.clearAllMocks(); }); test('显示 loading 状态', () => { fetchUser.mockImplementation(() => new Promise(() => {})); // 永不返回 render(<UserProfile userId={1} />); expect(screen.getByText('加载中...')).toBeInTheDocument(); }); test('成功加载后显示用户信息', async () => { const mockUser = { name: '张三', email: 'zhangsan@example.com' }; fetchUser.mockResolvedValue(mockUser); render(<UserProfile userId={1} />); await waitFor(() => { expect(screen.getByText('张三')).toBeInTheDocument(); expect(screen.getByText('zhangsan@example.com')).toBeInTheDocument(); }); }); test('请求失败时显示错误信息', async () => { const error = { message: '网络错误' }; fetchUser.mockRejectedValue(error); render(<UserProfile userId={1} />); await waitFor(() => { expect(screen.getByText(/出错了:网络错误/)).toBeInTheDocument(); }); }); });看,连等待异步的waitFor都帮你写好了。你只需要改一下错误信息的正则,或者加几个边界测试(比如 userId 为空)。
三、进阶:让 AI 生成更全面的测试
你可以在提示词里详细要求:
除了基本测试,还需要测试:
- 当 userId 变化时,会重新请求数据(之前的请求应被忽略或取消)
- 组件卸载时,不应再调用 setState
- 快照测试(可选)
AI 会给你生成类似:
test('userId 变化时重新获取数据',async()=>{constmockUser1={name:'User1'};constmockUser2={name:'User2'};fetchUser.mockResolvedValueOnce(mockUser1);const{rerender}=render(<UserProfile userId={1}/>);awaitwaitFor(()=>expect(screen.getByText('User1')).toBeInTheDocument());fetchUser.mockResolvedValueOnce(mockUser2);rerender(<UserProfile userId={2}/>);awaitwaitFor(()=>expect(screen.getByText('User2')).toBeInTheDocument());expect(fetchUser).toHaveBeenCalledTimes(2);});连rerender都懂,你还想怎样?
四、效率对比:手写 vs AI
| 步骤 | 手写时间 | AI 时间 |
|---|---|---|
| 写第一个测试(渲染 + loading) | 10min | 5s |
| 写成功场景 + mock | 15min | 5s |
| 写错误场景 | 10min | 5s |
| 写 userId 变化场景 | 15min | 5s |
| 调试断言 | 20min | 5min |
| 总计 | 70min | ~6min |
速度提升 10 倍以上。而且 AI 不会忘记清理 mock、不会漏掉waitFor。
五、真实故事:我用 AI 补完了 2000 行老代码的单测
接手一个电商项目的购物车模块,几乎没测试。我写了脚本,把每个组件文件内容喂给 GPT-4(分批,用 API),让它输出测试代码。然后手动改几个断言,跑一遍。两个晚上,覆盖率从 12% 升到 86%。测试妹子在群里发了个烟花表情,我回了个狗头。
六、注意事项(坑)
- AI 生成的 mock 路径可能错,比如
jest.mock('./api')如果你的 api 文件是services/api.js,需要手动改。 - 异步测试里
waitFor的超时,有些场景需要增加 timeout 配置。 - 不要盲目相信:AI 可能会生成冗余测试(比如测试
div的 className),需要你删除。 - 快照测试:AI 喜欢生成
toMatchSnapshot(),但快照容易“假绿”,建议换成具体的断言。
七、总结:AI 不是来取代你,是来帮你下班的
- 用 AI 生成单测模板,再人工微调,效率翻 10 倍。
- 适合重复性高、边界条件多的纯函数和 React 组件。
- 业务逻辑复杂、需要特定上下文的,AI 可能不准,但至少给你搭好架子。
- 以后测试妹子再催你,你可以说:“已经在写(让 AI 写)了。”
最后送大家一句话:AI 写单测,你喝咖啡。测试全绿,准点下班。
评论区聊聊:你试过用 AI 写单测吗?有没有翻车?
