302个测试文件,5070条测试,全部跑在Node环境里。没有jsdom,没有React Testing Library,没有render()。AI代理写的组件测试,连一个React元素都没渲染过。
这听起来像技术债爆炸前的宁静。但过去一周,他们用这个配置上线了YouTube流水线UI——上传队列、分析仪表盘、带元数据编辑的搜索。全部严格TDD。
不是没条件加浏览器环境,是算完账后主动放弃的。
两条路,都太贵
加jsdom意味着两个选择:要么把5070条测试全迁到浏览器环境,要么维护两套配置。前者是几个月的重构工程,后者是持续的认知负担。团队选了第三条路——用正则表达式读源码字符串。
代码长这样:
const content = fs.readFileSync('YouTubeDashboard.tsx', 'utf-8');
// 组件导出了吗?
expect(content).toMatch(/export\s+(const|function)\s+YouTubeAnalyticsPanel/);
// 调了正确的API端点吗?
expect(content).toMatch(/\/api\/youtube\/analytics/);
// 日期选择器有7天/30天/90天选项吗?
expect(content).toMatch(/7d|7\s*days/i);
expect(content).toMatch(/30d|30\s*days/i);
expect(content).toMatch(/90d|90\s*days/i);
这种测试不会出现在任何教程里。但它确实能抓到真问题:漏掉的导出、写错的接口地址、忘掉的UI元素、该删没删的占位文本。
正则测试的脆性,反而成了教学案例
字符数假设会崩。早期有测试检查两个组件是否在1000字符内同时出现,结果实现代码比预期长,测试挂了,代码却是对的。修复方案是改查关系不查距离:expect(content).toMatch(/tab.*trust|trust.*TrustScoreDashboard/s)——确认tab系统引用了组件,不管中间隔多少行。
否定断言出奇地好用。整套测试里最有价值的一条:
expect(content).not.toMatch(/coming in OAS-130-T2/);
每个YouTube tab最初都是占位文案"coming in OAS-130-T2"。组件实现后,这条测试确认占位符真的被替换了。简单,但抓得住一类典型bug:组件写了,却忘接进tab容器。
真正的信心从哪来
字符串匹配只解决结构问题。运行时行为靠服务层测试兜底——API契约、状态转换、副作用触发。UI测的是"有没有",服务测的是"对不对",两者拼起来覆盖大部分风险。
这套策略有个隐含前提:组件足够薄。业务逻辑下沉到hooks和services,UI层只剩布局和数据映射。如果组件里塞满条件分支和本地状态,正则测试会迅速失效。
AI代理在这里成了催化剂。它写代码的速度倒逼团队简化架构——复杂组件AI搞不定,薄组件AI量产,人只审关键路径。测试策略跟着架构走,不是反过来。
有个细节值得玩味:团队没禁用AI写测试,但限制了AI能用的工具。它不能mount组件、不能click按钮、不能断言DOM输出,只能读文件、写正则、跑Node。约束催生创造力,或者说,逼出了被浏览器测试惯坏时不会想的方案。
5070条测试全绿的时候,没人关心它们是不是"正确"的测试。只关心下次重构会不会红。目前看,红的都是该红的。
如果AI代理明天能跑浏览器环境了,他们会切回去吗?团队的原话是:"先算迁移成本,再算维护成本,然后发现我们现在这套还没成为瓶颈。"
热门跟贴