以测试为盾,重构为矛——老旧前端系统迭代中的“测试先行”实践总结

在耦合深、逻辑杂、文档少的老旧系统中,如何安全地向前走?我们用 Vitest + AI 辅助生成测试用例,构建了一套"以测试用例为验收标准"的迭代模式。

一、背景与困境

我们负责的业务模块是一个服役超过N年的前端系统,技术栈为 Vue3 + TypeScript。随着业务快速演进,代码逐渐暴露出典型的老旧系统特征:

  • 组件耦合深:父子组件通过多层 props 传递状态,兄弟组件共享全局 Store,改动一个组件往往"牵一发动全身"
  • 业务逻辑分散:部分逻辑在组件生命周期中,部分在自定义 Hook 中,还有一部分藏在工具函数里
  • 测试覆盖率近乎为零 :历史迭代追求速度,几乎没有单元测试,回归完全依赖人工 - 国内有一段时间是在推崇写单元测试, 但是薪资待遇没变, 事变多了, 工时没有增加, 基本很多团队是不太愿意做这个事情了
  • 文档缺失:业务规则只存在于少数核心开发者的记忆中
  • 测试用例不全: 人员变动, 测试用例可能只有某几次的版本,导致改动影响很困难。

每次需求迭代,开发人员都如履薄冰------改一行代码,不确定会影响到哪里

调试时间长, 测试范围模糊,不确定。

目前有遇到 嵌套 7-8层的 组件, 还有 组件之间各种传递大对象(50+字段)以上的。 调试的时候数据源复杂, 场景多变, 多个人员迭代, 参数传递越来越多, 实在是迭代不动。

单个模块代码爆炸 3000+ 行的逻辑。

二、破局思路:以测试用例驱动开发

我们引入的核心思想是:在修改业务代码之前,先为现有行为编写测试用例,让测试用例成为"安全网"和"行为说明书"。

有一些功能, 是人工就明显可以判别的 , 可以作为 背景梳理出来。 其他的已经是代码中存在的, 但是没有注释, 功能耦合严重的, 就依赖AI梳理。

具体工作流如下:

markdown 复制代码
1. 确定要修改的业务范围(某个组件 / 某个 Hook / 某个工具函数)
2. 将当前代码 + 相关依赖(props、store、外部接口)交给 AI
3. AI 辅助生成该模块的单元测试用例(Vitest)
4. 运行测试 ------ 此时测试应该全部通过(绿色)
5. 开始修改业务逻辑
6. 再次运行测试 ------ 如果变红,说明改动影响了预期行为,需要排查
7. 所有测试变绿后,提交代码

这个模式的核心价值在于:测试用例不是事后补充,而是事前锁定的"行为基线"

三、技术选型:Vitest

我们选择 Vitest 作为测试框架,原因如下:

特性 优势
与 Vite 生态无缝集成 项目已使用 Vite 构建,零配置成本
极快的执行速度 采用原生 ESM 和 SWC,测试反馈即时
Jest 兼容 API 学习成本低,describe / it / expect 语法通用
强大的 Mock 能力 vi.mock 轻松隔离外部依赖

四、AI 在流程中的角色:测试用例生成器

我们并没有让 AI 直接修改业务代码,而是将 AI 定位为 "测试用例辅助生成工具"

以某一个组件(最小单元) 为例, 将 某个组件要的 输入都 整理出来, 给 到AI, 提示词就是

复制代码
补充 xx 文件的 vitest测试用例, 根据我提供的测试数据, 如果场景是一致的, 列举一种场景即可。

前提是 vitest 都配置好了。 这个也比较简单。

特别是 某一个组件, 在多个入口场景被使用, 那么 就应该 明确列举一下

注意::大模型是有上下文限制的, 不要一次对多个模块补充测试用例, 最小单元去做测试用例补全。

  • 模块1-xx入口; props 入参数据
  • 模块2-xx入口; props 入参数据
  • 模块3-xx入口; props 入参数据

...

AI 生成测试用例的效果

维度 效果
覆盖度 覆盖正常路径、边界条件、异常情况
效率 从手动编写 30 分钟 → AI 生成 + 人工修正 5 分钟
质量 需人工校验边界条件和业务规则是否准确,AI 可能遗漏隐性规则
可读性 测试用例本身成为了"可执行的文档"

五、测试用例如何帮助我们安全迭代

场景一:重构组件内部逻辑

我们要将 OrderCard 中的状态判断逻辑抽取到一个自定义 Hook useOrderStatus 中。

  • 修改前:运行测试 → 全绿 ✅
  • 修改后:运行测试 → 如果变红 🔴,说明抽取逻辑时遗漏了某个分支条件
  • 修复:对比测试预期,补全逻辑,直到全绿

场景二:修改公共工具函数

formatPrice 原本只支持两位小数,新需求要支持三位小数。

  • 修改 formatPrice 后,所有依赖它的组件测试都会运行
  • 如果某个组件测试变红,说明该组件对金额格式有隐性依赖(比如只取两位显示)
  • 这提醒我们:要么修改组件适配新格式,要么在工具函数中做兼容处理

场景三:依赖升级或 API 变更

后端接口字段从 order_status 改为 status

  • 修改数据映射层后,跑一遍全量测试
  • 变红的测试精准指出哪些组件还在使用旧字段名
  • 相比人工排查,节省数小时

六、落地过程中的挑战与应对

挑战 应对策略
组件依赖过深,难以单独测试 使用 vi.mock 模拟子组件和 Store,聚焦当前单元
AI 生成的测试用例有误 人工 Review 并修正,逐步沉淀测试模板
测试环境与真实环境差异 补充集成测试,但单元测试仍作为第一道防线
团队不熟悉测试编写 AI 辅助降低门槛,但要求团队理解测试意图,而非盲目信任
测试执行时间变长 Vitest 的 watch 模式 + 只运行变更相关测试,保持反馈速度

小结

越是老旧系统, 人工维护的成本和精力越大。 在借助AI的帮助下, 思考这种场景如何破局。 从一上来先改代码的思维 变成 先补业务场景的边界, 再基于边界决定如何修改

我们后面对于复杂业务场景, 可能有2种比较好的选择

  • 基于当前的测试用例,打补丁,测试用例边界已经梳理清楚 (好迭代的场景,或者打补丁的代价和代码的复杂度不大), 可直接 给AI 投喂准确的需求, 迭代
  • AI 结合测试用例,发现这个 模块 (方法, 组件,接口) 不适用了, 直接将某个模块可以 copy一份, 将不要的逻辑删除, 再进行迭代,可能开发成本+测试成本更低,影响范围更小。

系统越是庞大, 越是老旧, 越是依赖人口口相传的地方, 基于这套方式的实践,在下一次迭代的意义越是明显。

相关推荐
攀小黑1 小时前
vue3+Web Speech API 封装了一个弹窗语音输入
前端·macos·xcode
roamingcode1 小时前
4.5 小时,从一句话需求到可安装的 Chrome 插件:一次 AI 结对开发的完整复盘
前端·人工智能·chrome·claude·codex
️学习的小王1 小时前
Windows Claude Code 接入 Playwright‑MCP,调用本机Edge浏览器(避坑完整教程)
前端·windows·edge
律宏阔1 小时前
CloakBrowser 开发踩坑笔记
前端·浏览器
Made in Haven7122 小时前
HTML课程笔记补2
前端·笔记·html
Cry丶2 小时前
Vue 3 业务管理页面实战:组件拆分、父子通信与弹窗复用
前端·javascript·vue.js·父子通信·组件拆分·弹窗复用
雪芽蓝域zzs2 小时前
Vue前端配置路由通配捕获 404
前端·javascript·vue.js
计算机魔术师2 小时前
Anthropic 发布电商 Agent 架构与生产实践指南,并开源 commerce-agents 参考实现
前端
IMPYLH2 小时前
HTML 的 <ol> 元素
前端·html