工程验证:XP、TDD、BDD 与契约测试
开发方法最终需要落到“怎样知道这次修改正确”。Scrum 可以安排工作,却不规定如何验证租户隔离;Agent 可以生成代码,却不负责决定业务预期。工程实践连接需求、实现和运行证据,减少“页面正常但行为错误”的情况。
XP 将小发布、简单设计、测试、重构、持续集成、协作和可持续节奏结合起来。这里选择与日常改动直接相关的实践:用 BDD 示例澄清行为,用 TDD 缩短实现反馈,用契约测试约束模块边界,再用集成和端到端检查验证真实连接。
BDD 先让业务行为可讨论
BDD 强调业务、开发和测试围绕具体示例共同澄清行为。Given / When / Then 是常用表达形式,但写了这种格式并不自动完成 BDD;关键是参与者确认示例揭示的规则。
订单导出可以从正常、拒绝和恢复三类行为开始:
gherkin
Scenario: 财务导出所属租户的订单
Given 财务用户拥有订单导出权限,且属于租户 A
When 用户请求导出指定时间范围内的已支付订单
Then 文件只包含租户 A 的匹配订单和白名单字段
Scenario: 下载其他租户的文件
Given 用户属于租户 B,导出任务属于租户 A
When 用户使用该任务标识请求下载
Then 系统拒绝访问,不返回文件内容第二个场景揭示了容易遗漏的规则:创建任务时鉴权并不等于下载时也安全。错误码、是否隐藏资源存在性和日志策略还需按项目约定确定,不应由测试作者随意选择。
TDD 用失败检查引导局部实现
TDD 的循环是先写一个能失败的行为测试,再用最小实现使它通过,最后在测试保护下重构。对于已复现缺陷,要确认测试先因目标问题失败;若失败原因只是数据库未启动,就还没有复现业务缺陷。
例如修复导出查询遗漏租户条件,准备两个租户的订单,断言租户 A 的结果不包含 B。先在旧实现上看到隔离断言失败,再补过滤条件,检查通过后整理查询结构。这个测试对准缺陷因果关系,比断言“调用了某个私有辅助函数”更能保护行为。
前后差别可以用缩小的伪代码表示,实际查询 API 以仓库为准:
ts
// 修改前:仅按时间读取,遗漏租户范围。
const rows = await orders.find({ paidAt: range })
// 修改后:租户标识来自服务端鉴权上下文。
const rows = await orders.find({ tenantId: auth.tenantId, paidAt: range })不要直接信任请求体中的 tenantId,也不要为了测试通过把预期改成当前结果。TDD 适合状态规则、计算、可复现缺陷和可控接口;探索交互或诊断复杂环境时,可以先做试验,再将稳定行为转为测试,而不是强迫所有研究都从单元测试开始。
契约、集成与端到端各自检查什么
契约测试检查消费者和提供者对接口的理解是否一致。例如前端期望任务状态和文件地址,后端改变字段时应被及时发现。OpenAPI 和类型检查可以校验部分结构,但通常不能独自证明权限、资源隔离和真实异步处理。
集成测试检查真实依赖之间的配合:任务是否入队,Worker 能否读取,文件能否保存。端到端测试通过真实入口确认用户能完成导出,并检查失败、重试和下载。不能因 Mock 返回成功,就认定队列和存储已经可用。
| 验证层 | 适合检查 | 不足以证明 |
|---|---|---|
| 单元 | 金额、字段白名单、状态转换 | 数据库和队列真实连接 |
| 契约 | 请求、响应、错误和状态兼容 | 业务安全与实际吞吐 |
| 集成 | 查询、队列、存储、鉴权配合 | 完整用户体验和所有环境配置 |
| 端到端 | 创建任务到授权下载 | 大规模性能和所有异常组合 |
| 性能与恢复试验 | 并发、资源、超时、中断 | 未覆盖环境下的绝对保证 |
测试组合应随风险调整。稳定纯函数可以主要用单元测试,跨服务导出必须补集成;高数据量要有基准和资源检查。没有必要为每个低风险文案修改写复杂测试,但应实际查看文字、布局和相关链接。
AI 如何参与而不形成自证
让 AI 根据已确认的规则补测试,是有效辅助;让它按当前实现推导全部预期,容易把缺陷固化。行为预期由业务示例和已有合同决定,测试作者再确认断言是否能发现目标错误。
对 Agent 修改,保留修改前基线、修改后结果和独立验收。独立可以是实际文件内容、不同租户请求、真实 HTTP 路径或浏览器操作,不要求重复所有测试。覆盖率反映执行范围,不能证明断言正确,也不能证明风险已经处理。
排错闭环
检查失败后,先区分环境不可用、测试夹具错误、规格变化和实现缺陷。环境问题修环境;夹具错误修数据;需求变化同步规格和预期;实现缺陷保留复现并修代码。直接删除失败测试或扩大超时,可能只是隐藏现象。
完成时应能解释失败如何触发、修复作用于哪里、检查覆盖什么、还有哪些未验证条件。更多存量项目操作可继续阅读 测试驱动 Agent 修改 和 验证与交付。
