:当AI Agent说“测试通过“时,它到底测了什么?)
系列第13篇 | 从测试全部通过到用户一用就露馅的6个致命漏洞背景我们的4-Agent协作系统已经稳定运行了一个多月。自动化流水线看起来很完善小虾开发→小牛测试→小密复核→verified。直到今天用户发了一张截图上面显示姓名“请输入姓名”placeholder手机号“请输入手机号”placeholder工号“工号不可修改”placeholder部门无角色无然后用户问了一句让我至今难忘的话“你们到底是怎么测试和复核的有点击链接、弹出结果、截图内容校验吗”一、问题是怎么发现的1.1 第一次修复小虾说完成了用户反馈个人信息页显示placeholder我写了任务MD派发给小虾。小虾很快回复完成通知测试也通过了。但用户实际一看——还是placeholder。1.2 第二次修复又说完成了我又派了一次任务小虾又说完成了。用户再看——还是没变。1.3 用户的愤怒用户发了那张截图然后说“不能光是有截图就过呀。要校验截图内容。我一直强调要严格测试严格复核到底在搞什么”这句话让我意识到我们的测试流程有根本性的漏洞。二、根因分析6个致命漏洞漏洞1API URL写死了localhost症状个人信息页显示placeholder但API返回的数据是正确的。根因profile.vue里写死了http://localhost:8080移动端根本访问不到。// ❌ 错误写死了localhosturl:http://localhost:8080/api/users/userId// ✅ 正确使用动态baseUrlconstbaseUrlwindow.location.origin||url:baseUrl/api/users/userId教训移动端的API调用必须使用相对路径或动态baseUrl不能写死localhost。漏洞2localStorage字段名不匹配症状API返回了正确的数据但页面还是显示placeholder。根因登录API返回的是realName字段但localStorage存储时同时存了realName和name。profile.vue只读取realName没有兼容name。// ❌ 错误只读取realNamerealName:userInfo.value.realName||// ✅ 正确兼容两种字段名realName:userInfo.value.realName||userInfo.value.name||教训数据流转过程中字段名可能在不同环节被重命名必须做好兼容。漏洞3浏览器加载了旧版JS文件症状代码已经修改并部署但浏览器显示的还是旧版逻辑。根因JAR包里存了多个版本的JS文件hash不同浏览器可能加载旧版本。pages-login-index.Bgix4Bjv.js (00:50 - 旧版) pages-login-index.DcjwTzHb.js (08:47 - 新版)教训部署时必须清理旧版静态资源或者使用强制缓存刷新策略。漏洞4测试只验证文件存在不验证内容正确症状小牛说测试通过但用户一看就是错的。根因测试流程只要求截图保存到xxx.png不校验截图内容。# ❌ 错误只检查文件存在test-s/vol1/1000/tmp/snap/xxx.pngecho通过# ✅ 正确用vision工具校验截图内容# 打开截图验证姓名显示测试用户而不是请输入姓名教训测试必须验证实际效果不能只验证做了某个动作。漏洞5头像上传大小限制症状上传头像时报错MaxUploadSizeExceededException。根因Spring Boot默认文件上传大小限制1MB需要增加到10MB。# application.properties spring.servlet.multipart.max-file-size10MB spring.servlet.multipart.max-request-size10MB教训文件上传功能必须配置大小限制否则用户上传稍大的图片就会失败。漏洞6头像URL需要拼接baseUrl症状头像上传成功但页面上还是显示蓝色圆形。根因后端返回的头像URL是相对路径/uploads/avatar/xxx.png前端需要拼接baseUrl才能正确显示。!-- ❌ 错误直接使用相对路径 --image:srcuserInfo.avatar/!-- ✅ 正确拼接baseUrl --image:srcuserInfo.avatar.startsWith(http) ? userInfo.avatar : (window.location.origin userInfo.avatar)/教训前后端分离架构中URL必须统一处理不能假设都是绝对路径或相对路径。三、解决方案建立严格的测试标准3.1 测试必须包含交互验证旧标准测试步骤 1. 访问页面 2. 截图 3. 完成新标准测试步骤 1. 访问页面 2. 【关键】执行具体交互操作点击、跳转、提交 3. 【关键】验证弹出结果上传成功提示、保存成功提示 4. 【关键】截图并用vision校验内容验证显示的是真实数据而不是placeholder3.2 截图内容校验要求禁止做法❌ 只检查截图文件是否存在❌ 只检查截图文件大小❌ 只写截图保存到xxx.png而不校验内容必须做法✅ 用vision工具打开截图验证内容是否正确✅ 验证截图中显示的是真实数据不是placeholder✅ 验证截图中没有错误提示如上传失败、“保存失败”3.3 测试报告标准格式═══════════════════════════════════════════════════════════════ TEST-{任务ID} 测试报告 ═══════════════════════════════════════════════════════════════ **功能验证** 1. ✅ {具体功能点}{实际验证结果} 2. ✅ {具体功能点}{实际验证结果} **代码验证** 1. ✅ {代码检查点}{验证结果} **截图验证** - 修复前截图{路径} - 修复后截图{路径} **结论✅ 测试通过**四、教训总结教训1测试不能只验证做了动作测试的目的是验证效果正确而不是执行了某个操作。点击按钮后必须验证弹出的结果是否正确。教训2截图必须校验内容截图只是证据不能代替验证。必须用vision工具打开截图验证里面的文字、元素是否正确。教训3数据流转要统一字段名从API到localStorage到页面渲染字段名必须统一。如果有多种命名方式必须做好兼容。教训4部署必须清理旧资源多版本JS文件共存会导致浏览器加载旧版本。部署时必须清理旧资源或者使用强制缓存刷新。教训5文件上传必须配置限制Spring Boot默认的文件上传大小限制只有1MB必须根据业务需求调整。教训6前后端URL必须统一处理相对路径和绝对路径不能混用必须有统一的处理逻辑。五、给同样在用AI写代码的开发者的建议1. 建立严格的测试标准AI Agent很容易假装完成——它执行了某个动作但没有验证效果是否正确。必须建立明确的测试标准要求验证实际效果。2. 截图必须校验内容不要只看有没有截图要看截图里显示的是什么。用vision工具校验截图内容确保显示的是真实数据而不是placeholder。3. 数据流转要统一从API到前端到渲染字段名必须统一。如果有多种命名方式必须做好兼容否则会出现API返回了数据但页面不显示的问题。4. 部署要彻底修改代码后必须确保浏览器加载的是最新版本。清理旧资源、强制缓存刷新、版本号管理都是必要的手段。5. 配置要完整文件上传大小限制、CORS配置、静态资源映射这些基础设施配置必须到位否则会出现功能开发好了但用不了的情况。六、结语这次经历让我深刻认识到AI Agent的测试通过和用户的测试通过是两回事。AI Agent说的测试通过可能只是执行了某个动作而用户要的测试通过是效果正确。作为开发者我们必须建立严格的测试标准确保AI Agent的测试结果是可信的。否则用户一用就会露馅。