ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

面试官问:你用 AI 编程半年了,那怎么保证 Claude Code 写出来的代码是对的?

面试官问:你用 AI 编程半年了,那怎么保证 Claude Code 写出来的代码是对的? 1. 面试官真正在问什么AI 编程的代码正确性怎么落地Claude Code 这类 AI 编程工具本质是在做概率性的代码补全。它能根据上下文猜出你想要的函数签名、循环结构、甚至一整套 Express 路由但它没有语义理解也不会主动替你想边界条件。你让它写一个用户登录接口它可能写得漂漂亮亮却漏掉 token 过期处理你让它解析日志它可能忘了空行会直接抛异常。所以面试官问「怎么保证 Claude Code 写出来的代码是对的」他真正想确认的是三件事你知不知道 AI 会在哪里出错你有没有一套可重复的验证动作以及这套动作是不是已经固化进你的工程流程而不是靠你每次手动 review 碰运气。这篇就围绕两条主线展开测试驱动开发TDD和类型注解。前者让 AI 先写测试再写实现用测试用例当验证器后者让编译器在 CI 阶段就拦住类型错误。两条线合起来再配上一份可复制的 settings.json 配置骨架就是一套能讲清楚、也能跟做的质量保障闭环。适合已经在用 Claude Code 写业务代码、但还没把验证流程工程化的开发者。2. 前置准备TaoToken 接入与 Claude Code 环境要让 Claude Code 稳定跑起来先得把模型接入配好。我用的方式是 TaoToken 的 API 接入官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 注意 API 地址后面不加 UTM 参数。接入前你需要先在控制台创建一个 API Key。打开 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 登录后进入 API Keys 页面新建一个 key 并复制保存。这个 key 只显示一次丢了就得重建。拿到 key 之后Claude Code 的环境变量这样配。macOS 或 Linux 下编辑 shell 配置文件# 写入 ~/.zshrc 或 ~/.bashrc export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的keyWindows PowerShell 下用$env:ANTHROPIC_BASE_URL https://taotoken.net/api $env:ANTHROPIC_API_KEY sk-你的key配完执行source ~/.zshrc或重开终端然后跑claude --version确认 CLI 能正常启动。如果你还没装 Claude Code先按官方方式装好 CLI再回来配这两个变量。注意ANTHROPIC_BASE_URL 只写到 /api 这一层不要自己拼 /v1 之类的路径否则请求会 404。3. 可复制配置settings.json 骨架与验证钩子Claude Code 支持项目级配置放在项目根目录的.claude/settings.json。这份配置的核心作用是把「AI 写完代码后必须跑什么验证」固化下来而不是每次靠你口头提醒。{ permissions: { allow: [ Bash(npm run test:*), Bash(npm run typecheck), Bash(npm run lint), Bash(pytest:*), Bash(mypy:*) ], deny: [ Bash(rm -rf:*), Bash(git push --force:*) ] }, hooks: { PostToolUse: [ { matcher: Write|Edit, hooks: [ { type: command, command: npm run typecheck npm run lint } ] } ] } }这份骨架里有两个关键点。第一permissions.allow 把测试、类型检查、lint 命令加进白名单Claude Code 执行这些命令时不会反复弹确认流程更顺。第二hooks.PostToolUse 在每次 Write 或 Edit 之后自动触发 typecheck 和 lintAI 刚写完的文件如果类型不过关钩子会立刻报错你就能当场让它修而不是等到提交前才发现。Python 项目把命令换成对应的即可{ hooks: { PostToolUse: [ { matcher: Write|Edit, hooks: [ { type: command, command: pytest -q mypy . } ] } ] } }配置写完后在项目里跑一次claude进入交互随便让它改一个文件观察钩子是否触发。如果没触发检查 settings.json 的 JSON 格式是否合法以及 matcher 拼写是否正确。4. 测试先行流程让 Claude Code 先写测试再写实现配置就绪后进入核心动作测试先行。我试过直接让 Claude Code 写业务逻辑结果它经常漏掉边界条件所以现在固定成「先测试、后实现」的顺序。假设需要一个解析服务器日志行的函数parse_log_line返回结构化字典。第一步让 Claude Code 写测试# test_log_parser.py import pytest from log_parser import parse_log_line class TestParseLogLine: def test_valid_line(self): line 2024-03-15 10:30:45 ERROR [auth] User admin login failed from IP 192.168.1.1 result parse_log_line(line) assert result[timestamp] 2024-03-15 10:30:45 assert result[level] ERROR assert result[module] auth assert result[user] admin assert result[ip] 192.168.1.1 def test_missing_fields(self): line 2024-03-15 10:30:45 INFO [] Simple message result parse_log_line(line) assert result[user] is None def test_empty_line(self): with pytest.raises(ValueError, matchEmpty log line): parse_log_line() def test_malformed_timestamp(self): line invalid-timestamp WARN [test] msg with pytest.raises(ValueError, matchInvalid timestamp format): parse_log_line(line)测试覆盖了正常、字段缺失、空行、时间戳格式错误四类情况。第二步把测试文件交给 Claude Code让它按测试写实现# log_parser.py import re from datetime import datetime def parse_log_line(line: str) - dict: if not line or not line.strip(): raise ValueError(Empty log line) pattern r^(\S\s\S)\s(\w)\s\[([^\]]*)\]\s(.)$ match re.match(pattern, line) if not match: raise ValueError(Log line format not recognized) timestamp_str, level, module, message match.groups() try: datetime.strptime(timestamp_str, %Y-%m-%d %H:%M:%S) except ValueError: raise ValueError(Invalid timestamp format) user None ip None user_match re.search(rUser ([^]), message) if user_match: user user_match.group(1) ip_match re.search(rIP (\S), message) if ip_match: ip ip_match.group(1) return { timestamp: timestamp_str, level: level, module: module, user: user, ip: ip }这套流程为什么有效因为测试用例本身就是规格说明。AI 在写实现时必须让test_empty_line通过就必须处理空行必须让test_malformed_timestamp通过就必须校验时间戳格式。它没法偷懒跳过这些路径。如果实现跑不过测试把失败信息贴回给 Claude Code让它自己修通常一到两轮就能全绿。5. 类型注解与运行时断言让编译器当第一道防线测试管的是行为类型注解管的是接口契约。AI 生成的代码经常在运行时因为类型不匹配而崩比如把字符串当数字算。所以我在提示词里会明确要求生成代码必须带完整类型注解和运行时断言。以 TypeScript 的折扣计算函数为例给 Claude Code 的指令是「生成 calculateDiscount包含完整类型注解、输入验证断言和 JSDoc」。它产出的结果// discount.ts /** * 计算商品折扣后的价格 * throws {Error} 如果 price 无效 */ function calculateDiscount( price: number, couponCode: string | null, isVIP: boolean ): number { if (typeof price ! number || price 0) { throw new Error(Invalid price: must be a positive number, got ${price}); } if (couponCode ! null typeof couponCode ! string) { throw new Error(Invalid couponCode: must be string or null); } if (typeof isVIP ! boolean) { throw new Error(Invalid isVIP: must be boolean); } let discount 0; if (isVIP) { discount 0.1; } if (couponCode) { const couponDiscountRate getCouponDiscount(couponCode); if (couponDiscountRate 0) { discount Math.max(discount, couponDiscountRate); } } discount Math.min(discount, 0.5); const finalPrice price * (1 - discount); return Math.round(finalPrice * 100) / 100; } function getCouponDiscount(code: string): number { const couponMap: Recordstring, number { SAVE10: 0.1, VIP20: 0.2, BIG50: 0.5, }; return couponMap[code] || 0; }类型注解让tsc在编译阶段就能发现调用方传错类型运行时断言则防止边界值静默失败。两者叠加AI 代码在编译和运行两个层面都有拦截。Python 项目同理用mypy做静态检查函数签名写全- dict、参数标str配合pytest一起跑。6. 验证请求与成功结果跑通一次完整闭环配置和代码都就位后跑一次端到端验证。在项目根目录执行npm run typecheck npm run lint npm run test或者 Python 项目mypy . pytest -q成功时你会看到类似输出 tsc --noEmit eslint src --ext .ts jest PASS src/discount.test.ts calculateDiscount ✓ 正常价格加 VIP 折扣 ✓ 优惠券折扣取最大值 ✓ 非法价格抛错 Tests: 3 passed, 3 total如果类型检查或测试失败Claude Code 的 PostToolUse 钩子会在你编辑文件后立刻报出错误行号和原因。把这段错误信息直接贴回对话让它修复再跑一次直到全绿。这个过程就是面试官想听到的「反馈循环」AI 写 → 验证 → 失败 → AI 修 → 再验证 → 通过。想单独验证模型对话是否正常可以打开 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发一条测试消息确认返回正常。如果你打算长期用 Claude Code 做编码和 Agent 任务可以看下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 按用量规划更省心。7. 本篇常见错排查钩子不触发检查.claude/settings.json是否在项目根目录JSON 是否合法用python -m json.tool验证matcher 是否写成Write|Edit而不是write。typecheck 报找不到命令确认package.json的 scripts 里有typecheck定义比如typecheck: tsc --noEmit。没有就先补上。pytest 收集不到测试文件名必须以test_开头或_test结尾函数名以test_开头。放在项目根目录或tests/下并在pyproject.toml里配好testpaths。API 请求 401检查ANTHROPIC_API_KEY是否复制完整有没有多余空格。key 只在创建时显示一次如果丢了就去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 重新生成。请求 404 或路径错误确认ANTHROPIC_BASE_URL是https://taotoken.net/api不要加/v1或结尾斜杠。接入细节可对照文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。AI 反复改不对同一个测试把测试文件和失败输出一起贴给它并明确说「只改实现不要改测试」。如果它想改测试来绕过失败直接拒绝测试是规格不能动。类型检查通过但运行时仍崩说明缺运行时断言。在提示词里加一句「所有外部输入必须做运行时类型校验」让它补上typeof或isinstance检查。8. 把验证闭环讲成你的工程能力回到面试场景。当面试官问「怎么保证 Claude Code 写的代码是对的」你可以这样组织回答我用测试先行让 AI 先写覆盖正常、异常、边界三类情况的测试再按测试写实现我用类型注解加运行时断言让编译器和运行时双重拦截类型错误我把 typecheck、lint、test 固化进 settings.json 的 PostToolUse 钩子每次 AI 改完文件自动跑失败就把错误贴回去让它修直到全绿。这套流程不依赖我信任 AI而是依赖可重复的验证动作。这套东西的价值不只在面试。日常写业务代码时它把 AI 从「天马行空的诗人」变成「按规格编程的工人」。你省下的不是打字时间而是排查那些隐蔽边界 bug 的时间。Claude Code 的接入和配置入口都在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 配好之后把 settings.json 骨架复制进项目先跑通一次 typecheck 加 pytest 的闭环再逐步把钩子扩展到更多验证命令。
返回列表