接受集成之前,先读懂 mock 演示

使用 AI 辅助编写与复核。

本文目录

本地预览可以展示预期交互,而它的服务响应仍然来自示例数据。这样的原型可能很有用。接受更大的任务之前,先确认哪些部分实际运行过,哪些结果是示例数据提供的。

提出一个具体问题:当视图显示“Saved”时,是应用展示了预先提供的成功值,还是调用了预期的适配器、收到了真实服务结果,或是在后续读取中验证了该值?这些是不同的证据。

Python 的 mock 文档 介绍了如何替换被测系统的某些部分,并断言这些替代对象如何被使用。这是一种有用的测试技术。针对替代对象的检查,只能确立关于那条测试路径的主张;它并没有观察被替代的服务。

区分完整请求与原型里程碑

考虑下面这个笔记应用的虚构请求:

任务 NOTE-5:让有权限的用户把 N17 的标签从 Draft 改为 Ready。

完整流程:
只有实际服务确认变更之后,才显示 Saved。
用户重新打开记录时,读取它当前已保存的标签。
如果保存失败,解释未保存的状态,并保留用户拟定的标签,
供其修正。使用应用现有的访问检查;
不要自行发明新的权限模型。

仅限首次交付:
准备可检查的本地原型源文件,使用示例响应,
明确标注未连接服务,附上边界图,并检查
假响应状态模型。记录尚未进行的浏览器检查。
本里程碑不连接服务、不使用真实记录,也不部署。

这份请求允许交付原型,但没有把原型定义为完整集成。分别审查这两类交付,既能避免拒绝有用的原型工作,也能避免接受尚未运行过的服务路径。

这个案例中的一切都是编写的教学材料:记录 N17、请求、示例数据、组件和审查回复。没有涉及真实记录或提供方。

追踪预先提供的成功值

初始示例数据是:

{"record_id":"N17","label":"Draft"}

收到保存请求时,fake 适配器返回这份单独的合成响应:

{"record_id":"N17","label":"Ready","saved":true}

它不联系服务。在这个纯 Python 教学对应模型中,完整的适配器和本地模型如下:

class FakeLabelAdapter:
    def __init__(self):
        self.calls = []

    def save_label(self, record_id, label):
        self.calls.append((record_id, label))
        return {"record_id": record_id, "label": label, "saved": True}


class DemoPanel:
    def __init__(self, adapter):
        self.adapter = adapter
        self.label = "Draft"
        self.notice = "Not saved"

    def save(self):
        response = self.adapter.save_label("N17", "Ready")
        self.label = response["label"]
        self.notice = "Saved" if response["saved"] else "Not saved"

saved 字段为 true,是因为 fake 返回了 true。模型的提示状态由这个字段决定。这个小示例的其他地方,没有隐藏着一次存储写入。

配套的独立 HTML 原型 提供了对应的本地交互,并醒目标注 LOCAL MOCK DEMO · NO NETWORK OR STORAGE。它没有服务调用,选择 Reopen fixture 时,会把显示标签重置为初始值。作为本文的一部分,它的浏览器行为没有被运行过。对 Python 对应模型的方法检查,与浏览器点击或页面渲染检查是分开的。

评价演示之前,先画出边界

原创示意图:本地示例数据、fake 适配器和未连接的服务

阶段 这个产物包含什么 这里可用的证据
初始本地状态 N17 初始值为 Draft 完整源文件和编写的示例数据
fake 保存调用 记录 N17/Ready 这组参数,并返回成功值 实际的本地 Python 模型检查
本地状态变化 模型变为 Ready,提示为 Saved 实际的本地 Python 模型检查
HTML 事件与渲染 源文件根据假响应设置标签和提示 已提供源文件;未运行浏览器
实际适配器与服务 没有连接任何调用路径 未运行
持久值与后续读取 没有使用存储 未运行
当前用户的访问权限 示例中不存在真实身份或访问路径 未运行

如果有人实际运行本地预览,并看到 Ready,这项观察可以支持“使用给定示例数据进行了渲染”的结论。但它仍然不能证明服务保存成功。对于这里提供的文件,连这项渲染观察也尚未进行;上面的图片是边界示意图,不是浏览器截图。

检查小型模型实际做了什么

本地教学运行使用 Python 3.9.6,检查了两件事:

  1. 调用 save() 会在 fake 中精确记录 ("N17", "Ready"),并把该模型状态改为 Ready / Saved。
  2. 使用同一个适配器创建新模型,会再次从 Draft / Not saved 开始。适配器中仍只记录了一次调用;它没有提供已保存记录的读取。

两项模型检查都通过了。它们没有运行 HTML、JavaScript、浏览器、服务、身份验证或存储。实际输出保留在本地模型日志中。

下面是状态历史,观察范围保持明确:

步骤 模型动作 之后的标签 / 提示 能得出什么
1 构造第一个模型 Draft / Not saved 初始示例状态
2 调用它的 save 方法 Ready / Saved 此模型使用了假响应
3 检查 fake 调用 仍为 Ready / Saved;记录了一次 N17/Ready 调用 预期参数到达了 fake
4 构造新模型 Draft / Not saved;同一个 fake 仍只有一次调用 示例没有持久化读取路径

第 4 步是这个教学原型本身的属性,不是实际观察到的真实服务故障。模型被设计为从 Draft 初始化,并且没有持久化。把它报告成“后端把保存丢了”会造成误导,因为这里没有联系任何后端。

fake 仍然有用。它让开发者无须配置服务,就能检查响应分支和预期调用。其他示例响应也可以用来运行失败分支,但这里提供的原型没有实现 NOTE-5 完整的失败处理。这是一项已经识别的后续工作,不是已完成的检查。

为每项验收主张匹配适当证据

关于 NOTE-5 的主张 原型能够支持什么 更大范围的主张还需要什么
请求把 N17 和 Ready 发送给选定的依赖 Python 对应模型把这些参数发送给了自己的 fake 验证实际应用的适配器路径和参数
给定的成功响应更新本地状态 已在 Python 模型中检查 检查实际组件、事件和渲染路径
视图显示预期标签 已提供可检查的 HTML 声称检查过之前,先在浏览器中观察渲染后的原型
服务保存了变更 这里没有任何证据观察到服务 获授权的真实保存路径的证据
重新打开时显示已保存的值 新模型构造会返回示例初始值 Draft 根据已接受的服务写入,检查实际的后续读取
保存失败时保留拟定标签并解释错误 这个仅有成功响应的示例没有实现 按适用契约实现并检查这条路径
只有有权限的用户才能修改记录 不存在真实用户或访问路径 检查并验证实际的访问控制
流程已经部署 这里没有发布产物或部署 单独的发布及其验证

集成决定不必要求所有可能的测试。它需要与承诺边界相关的证据。对于这份请求,关键缺口是从实际适配器经过服务、再到后续读取的这段路径,以及相关的失败和访问行为。重复仅针对示例数据的检查,并不能跨过这段边界。

写出两种不同的验收回复

第一份回复接受实际请求的里程碑:

接受 NOTE-5 的原型源文件和 fake 状态模型里程碑。

给定 HTML 已明确标注为未连接服务的 mock 演示。
边界图标出了 fake 和未运行的服务路径。
记录的 Python 检查支持 fake 调用参数和本地状态变化,
包括新模型重置为 Draft。

这个决定覆盖这些源文件和模型产物。未检查浏览器交互,
实际保存、读取、访问和失败路径也尚未实现或接受。
保持完整 NOTE-5 流程未完成。

第二份回复针对“完整集成已经完成”这一拟议主张:

不要凭 mock 演示关闭端到端 NOTE-5 任务。
其中的 saved=true 来自假响应,不是服务结果。

下一步,在选定代码库中识别实际适配器、保存操作和后续
读取路径。返回有明确范围的集成方案,列出精确候选与文件、
适用的访问检查、失败行为,以及最小的相关验证步骤。

保留原型证据的原型标识。不要用编造的服务输出替换它,
也不要重复本地 fake 检查来证明持久化。
任何后续真实环境检查,都必须使用获授权的范围和数据。
这份规划回复不要求调用服务、设置账号、修改线上记录
或发布。

两份回复都没有把 mock 当成缺陷。一份接受有用且有限的产物;另一份保留原始请求中尚未满足的部分。

复用这份演示审查请求

按[原始需求和当前正在验收的里程碑]
审查[精确演示候选]。只读工作。

在适用时,追踪演示动作,从输入经过本地状态、适配器、
依赖、保存结果,再到后续读取。为每个阶段标注:
实际运行过、模拟、仅检查了源文件,或尚未确立。
标明精确的示例数据,以及预先提供的成功或失败值。

对每项主张,说明演示路径能支持什么,以及它没有跨过
哪条边界。fake 调用断言可以支持调用契约;
不能把它报告为观察了被替代的服务。
编写绘制的图片或尚未运行的 HTML,不能变成浏览器测试结果。

返回当前里程碑的限定范围决定,以及针对更大范围未满足
需求的最小后续方案或检查。保留有用的 mock 检查。
本次审查不调用账号、不修改线上数据、不安装服务,也不部署。
将实际执行与示例分开记录。

这样可以更好地使用演示:接受它已经确立的部分,保留示例数据用于后续开发,并要求提供跨越下一条边界所需的具体证据。