AI 辅助调试思路:从报错到根因
传统调试:报错 → Google → 翻 Stack Overflow → 试方案 → 不行 → 再试。Trae 把这个流程压缩了:
传统调试:报错 → Google → 翻文档 → 试方案 → 不行 → 再试 → 终于修好
Trae 调试:报错 → 丢给 AI → 分析根因 → 给出修复 → 搞定
但 AI 只是加速器,好的调试习惯依然重要。核心四步:
- 收集完整信息:报错信息、堆栈追踪、复现步骤
- 缩小范围:前端还是后端、逻辑错误还是类型错误
- 让 AI 分析:把信息喂给 Trae,让它定位根因
- 验证修复:AI 给的方案不一定对,跑测试确认
Chat 分析错误日志和堆栈
遇到报错,最直接的做法是把错误信息贴进 Chat,同时用 @file 引用相关代码:
@file:src/components/UserList.tsx
这个组件报了 TypeError: Cannot read properties of undefined (reading 'map'),
堆栈指向第 15 行。帮我分析根因,给出修复方案。
Trae 会结合文件内容和报错信息,告诉你数据还没加载完就调了 .map(),需要加空值检查。
多文件联合分析是 Trae 的强项。数据流跨了好几个文件时,一次引用多个文件:
@file:src/hooks/useUsers.ts
@file:src/components/UserList.tsx
@file:src/api/users.ts
用户列表偶尔白屏,帮我追踪数据从 API 到组件的完整链路。
Inline Edit 快速修复 Bug
Chat 分析完根因,按 Cmd + I 选中有问题的代码直接修。比如这段有 Bug 的代码:
function UserList({ data }) {
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
选中后输入”添加空值保护,data 为空时显示加载状态”,Trae 直接生成修复:
function UserList({ data }) {
if (!data) return <div className="loading">加载中...</div>;
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
常见修复场景速查:
| 场景 | 提示词写法 | 效果 |
|---|---|---|
| 空值保护 | ”添加 null/undefined 检查” | 自动加 guard clause |
| 类型修复 | ”修复类型错误,参数应该是 string[]“ | 修正类型声明 |
| 逻辑修复 | ”条件判断反了,应该是 >=“ | 修正逻辑运算符 |
| 异步修复 | ”这里缺少 await” | 补上 await 关键字 |
| 边界处理 | ”处理数组为空的边界情况” | 添加 length 检查 |
Builder 批量修复类似问题
同一类 Bug 出现很多次?用 Builder 批量处理:
扫描 src/components 下所有组件,找出直接对 props 调用 .map()、.filter()
但没做空值检查的地方,统一添加防御性代码。
要求:用可选链或 guard clause,数据为空时显示 fallback UI。
Builder 自动扫描、逐个修复,你只需要在关键节点确认。批量修 ESLint 报错也一样好用:
项目有 47 个 ESLint 错误(no-unused-vars、prefer-const、no-explicit-any),
帮我批量修复。对于 no-explicit-any,根据上下文推断合适的类型。
AI 生成单元测试:Jest / Vitest 实战
调试是治标,测试才是治本。看一个完整的例子——被测函数:
// src/utils/price.ts
export function calculateDiscount(
price: number,
discountPercent: number,
memberLevel: 'normal' | 'silver' | 'gold' | 'platinum'
): number {
if (price < 0) throw new Error('Price cannot be negative');
if (discountPercent < 0 || discountPercent > 100)
throw new Error('Discount percent must be between 0 and 100');
const multiplier = { normal: 1, silver: 1.05, gold: 1.1, platinum: 1.2 };
const discount = price * (discountPercent / 100) * (multiplier[memberLevel] || 1);
return Math.round((price - discount) * 100) / 100;
}
在 Chat 里输入 @file:src/utils/price.ts 用 Vitest 生成完整单元测试,覆盖正常、边界、异常,Trae 生成:
// src/utils/__tests__/price.test.ts
import { describe, it, expect } from 'vitest';
import { calculateDiscount } from '../price';
describe('calculateDiscount', () => {
describe('基本折扣计算', () => {
it('普通会员 10% 折扣', () => {
expect(calculateDiscount(100, 10, 'normal')).toBe(90);
});
it('白金会员享受最大折扣', () => {
expect(calculateDiscount(100, 10, 'platinum')).toBe(88);
});
});
describe('边界值', () => {
it('价格为 0', () => {
expect(calculateDiscount(0, 50, 'normal')).toBe(0);
});
it('折扣为 100%', () => {
expect(calculateDiscount(100, 100, 'normal')).toBe(0);
});
});
describe('异常输入', () => {
it('负数价格抛出错误', () => {
expect(() => calculateDiscount(-10, 10, 'normal')).toThrow('Price cannot be negative');
});
it('折扣超过 100% 抛出错误', () => {
expect(() => calculateDiscount(100, 150, 'normal')).toThrow('Discount percent must be between 0 and 100');
});
});
});
AI 生成集成测试与 E2E 测试
单元测试之外,Trae 也能写集成测试。引用路由和中间件文件,描述要覆盖的场景:
@file:src/server/routes/users.ts
@file:src/server/middleware/auth.ts
用 supertest 写集成测试:未登录返回 401、普通用户只能查自己、管理员查所有人。
E2E 测试用 Playwright,描述用户操作流程即可,Trae 会生成完整的页面交互测试代码。
测试覆盖率提升策略
不同项目类型的覆盖率目标参考:
| 项目类型 | 行覆盖率 | 分支覆盖率 | 函数覆盖率 |
|---|---|---|---|
| 工具库 / SDK | 90%+ | 85%+ | 95%+ |
| 业务后端 API | 80%+ | 75%+ | 85%+ |
| 前端组件 | 70%+ | 65%+ | 80%+ |
| 内部工具 | 60%+ | 50%+ | 70%+ |
用 Trae 补测试的流程:先跑 npx vitest run --coverage,然后在 Chat 里引用覆盖率文件,让 AI 针对低覆盖率模块补测试。
实战:调试 TypeScript 类型错误
TypeScript 类型错误是最头疼的 Bug 之一。看这个有问题的 hook:
// src/hooks/useApi.ts — 有类型错误
function useApi<T>(url: string) {
const [state, setState] = useState<{ data: T; error: string | null; loading: boolean }>({
data: null, // ❌ null 不能赋值给 T
error: null,
loading: true,
});
// ...
}
在 Chat 里让 Trae 修复,它会用可辨识联合类型重构:
type ApiState<T> =
| { data: null; error: null; loading: true }
| { data: T; error: null; loading: false }
| { data: null; error: string; loading: false };
function useApi<T>(url: string): ApiState<T> {
const [state, setState] = useState<ApiState<T>>({ data: null, error: null, loading: true });
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(res => res.ok ? res.json() as Promise<T> : Promise.reject(new Error(`HTTP ${res.status}`)))
.then(data => setState({ data, error: null, loading: false }))
.catch(err => err.name !== 'AbortError' && setState({ data: null, error: err.message, loading: false }));
return () => controller.abort();
}, [url]);
return state;
}
调用方可以根据 loading 和 error 自动收窄 data 的类型,不再需要手动断言。
实战:为现有代码补充测试用例
给老代码补测试是最常见的场景。假设有一个购物车服务:
// src/services/cart.ts
export class CartService {
private items: CartItem[] = [];
addItem(item: Omit<CartItem, 'quantity'>, quantity = 1): void { /* ... */ }
removeItem(id: string): void { /* ... */ }
updateQuantity(id: string, quantity: number): void { /* ... */ }
getTotal(): number { /* ... */ }
clear(): void { /* ... */ }
}
在 Chat 里引用文件,要求覆盖每个方法、边界情况和方法间交互,Trae 会生成包含添加、删除、数量更新、总价计算等完整测试。重点关注:重复添加累加数量、数量设为 0 自动删除、getItems() 返回副本不影响原数据这些容易遗漏的场景。
小结
| 层次 | 能力 | 对应模式 |
|---|---|---|
| 分析 | 理解报错、追踪根因、解释堆栈 | Chat |
| 修复 | 快速修 Bug、类型修正、逻辑修正 | Inline Edit |
| 预防 | 生成测试、提升覆盖率、批量修复 | Builder |
调试和测试是同一个质量保障闭环的两面。用 Trae 把这个闭环跑起来,代码质量会有质的提升。
调试是在已知的代码里寻找未知的错误,测试是在未知的场景里验证已知的逻辑。AI 不会替你思考该测什么,但它能帮你把”想到的”快速变成”跑得通的”。
相关文章
评论
加载中...
评论
加载中...