Skip to content

工程验证: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 的循环是先写一个能失败的行为测试,再用最小实现使它通过,最后在测试保护下重构。对于已复现缺陷,要确认测试先因目标问题失败;若失败原因只是数据库未启动,就还没有复现业务缺陷。

行为示例、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 修改 和 验证与交付。

别急,先让缓存热一下。