不写一行JS,也能做自动化测试:前端工程师用Claude Code完成全流程回归验证

起因:我们被“回归测试”拖垮的那周 那是上个月17号,周五晚九点。 服务器监控告警刚消,产研群消息已炸成红色瀑布流:“支付成功率跌到92%!”“订单页价格显示为NaN!”“发票模块白屏!”——三个紧急热修复塞进发布窗口,外加两个UI组件重构(Ant Design 5.x 升级引发的表单校验链断裂)。 我打开测试清单:27个核心路径,从登录态保持、搜索联想、购物车增删,到跨端同步、异常网络兜底……全靠手动点。四人轮班,手机支架架在MacBook上录屏,咖啡机24小时待命。凌晨两点,小王在测“优惠券叠加逻辑”,漏掉了“满300减50+店铺红包”组合下,结算页底部“立减¥50”文案未高亮;凌晨三点,我卡在“发票申请表单提交后,邮箱校验提示应为红色且聚焦”,却忘了验证“连续两次错误输入后,防暴击锁30秒”的交互状态。 崩溃发生在三点十七分。我盯着Playwright控制台里第12次重跑的test:regression套件,看着它又花47秒加载整个首页、跳转用户中心、展开侧边栏、点击“开发设置”——就为了验证一个按钮颜色从#1890ff改成了#1677ff。 我抓起保温杯砸向软垫(没真砸),吼出那句后来被截图传遍公司IM群的话: “连改个按钮颜色都要重跑整套E2E?这哪是测试,这是体力活!” 就在我瘫在椅子上刷手机想转移注意力时,手指无意识点开了Claude Code的网页版,把一段刚写的、带三处waitForSelector的脚本粘了进去。它没直接给答案,反而弹出一句反问: “你是否考虑过用自然语言描述验证逻辑,由AI生成可执行断言?” 我愣住。手指悬在键盘上方三秒。 不是“怎么写代码”,而是“怎么说人话”。 那一刻,我忽然意识到:我们花了80%时间把需求翻译成Playwright语法,却只留20%时间思考——这个需求,到底值不值得测? 尝试:从“写代码”到“说人话”的第一次迁移 我翻出Confluence里那份叫《V2.3核心回归用例》的Word表格——最后编辑时间是2021年8月,作者是已离职的前QA leader。里面写着: 搜索功能:输入关键词,展示结果,数据应合理 订单页:价格计算正确,支持修改数量 发票申请:邮箱格式校验,错误时提示明确 我把整页复制进Claude,写下prompt: “请基于以下业务规则,生成可在Playwright中直接运行的端到端断言代码,不修改页面交互步骤,只补充验证逻辑。所有选择器必须使用data-testid,禁用ID和class。若规则表述模糊,请先追问业务含义。” 它立刻回问: ❓ “‘数据应合理’具体指什么?例如:搜索‘苹果’是否应排除‘苹果手机’?结果数是否需大于0?是否有排序规则(如销量优先)?” 我愣了——这问题直戳痛点。我拉上产品经理,在茶水间白板上画了15分钟:原来“合理”=“匹配度>0.7且按GMV降序”,而这条规则,三年来只存在于他脑内。 接着它输出代码。但第一版栽在选择器上: // ❌ AI默认生成(错!项目不用id) await page.waitForSelector('div#loading'); expect(await page.locator('span.price').textContent()).toContain('¥'); 而我们项目规范是: // ✅ 正确写法(data-testid) await page.locator('[data-testid="loading-spinner"]').waitFor({ state: 'visible' }); expect(await page.locator('[data-testid="product-price"]').textContent()).toContain('¥'); 踩坑总结:AI没有上下文记忆。你没给它CSS规范文档,它就按Stack Overflow最高票答案猜。 实战:用Claude Code跑通真实回归流水线 我们决定拿最痛的“搜索结果页”开刀。流程如下: Step 1:语音转文字,拒绝脑内编译 我打开iPhone语音备忘录,对着麦克风说: “搜索框输入‘发票’,结果页顶部显示‘共12条匹配’,且第1条标题含‘电子发票’字样,点击第1条后URL包含/invoice/detail?id=,页面标题是‘电子发票详情’。” 转文字后粘贴进Claude,加一句: “生成Playwright断言块,要求:1)使用locator.waitFor({ state: 'visible' })替代waitForTimeout;2)对文本断言加.trim();3)URL校验用正则,注释说明匹配逻辑。” Step 2:Claude输出(带注释,可直接抄) // ✅ 验证搜索结果总数(容错:空格、换行、中文数字) const totalCount = await page.locator('[data-testid="search-result-count"]').textContent(); expect(totalCount?.trim()).toMatch(/共\s*\d+\s*条匹配/); // ✅ 验证首条标题含关键词(避免误匹配“纸质发票”) const firstTitle = await page.locator('[data-testid="search-result-item"]').first().locator('h3').textContent(); expect(firstTitle?.trim()).toContain('电子发票'); // ✅ 验证跳转URL(正则确保?id=后跟数字) await page.locator('[data-testid="search-result-item"]').first().click(); await page.waitForURL(/\/invoice\/detail\?id=\d+/); expect(await page.title()).toBe('电子发票详情'); Step 3:注入现有测试文件,仅改2处变量名 ...

March 27, 2026 · 智通