1574 字
约 5 分钟
14
S16-B04 · 端到端:跑通完整流程才算真正验证
2024-12-31
2026-11-07

适用读者:把"单测全绿"当成"完成"的开发者;用 AI 编程工具交付、需要验收判据的人。
前置:S16-B03、能启动一次完整应用(前端/后端/依赖服务)。
覆盖旧文:A-275 → 96 点(§3 harness 与架构规则、§4 代码示例);A-275 的"审查反馈提升"并入 A02。
扩展点:E-S16-004(E2E 最小集)。
上一篇:S16-B03 · 集成测试:Spring Boot Test 与 Testcontainers
下一篇:S16-J01 · 链路追踪基础。


1. 一句话结论

"做完了"必须由系统级证据定义,而不是由"我跑过单测"定义。 单元测试证明零件,端到端证明零件装在一起还能转——后者是发布前的唯一凭据。

声明 需要的证据
"功能实现了" 一条从入口到出口的脚本跑通,含断言
"没破坏别的" 同一套 E2E 全绿(回归)
"异常也处理了" 注入故障(依赖超时/返回错误)仍按预期降级

2. 为什么单测会系统性漏(A-275)

原文的 Electron 案例:渲染进程组件、预加载脚本、服务层三层各自单测通过,agent 宣布完成;实际点击导出按钮:文件路径格式不对、进度条无反应、大文件导出内存泄漏——5 个组件边界缺陷,单测一个都没发现。

四类缺陷与成因:

缺陷类型 具体形态 单测为什么漏
接口不匹配 渲染进程传相对路径,预加载脚本要绝对路径 两侧各自 mock,假设不一致
状态传播错误 迁移改了表结构,ORM 缓存持旧结构 每个测试都是全新 mock
资源生命周期 文件句柄/连接/socket 跨组件获取释放 测试各自创建销毁,不共享
环境依赖 配置差异、网络延迟、服务不可用 测试环境全 mock

原文的判断:"只有端到端测试能证明系统级缺陷不存在。" 并且——当 agent 知道要过 E2E 时,它的编码行为会改变:会考虑上下游接口、会遵守架构边界、会处理错误路径。


3. 把架构规则变成可执行检查(§3)

原文的关键工程手法:规则不要写在文档里,要写成脚本,进 harness。

// tools/check-arch-rules.ts —— 渲染进程禁止直接调用 Node API
import { readdirSync, readFileSync } from "node:fs";
const dir = "src/renderer";
const bad = readdirSync(dir, { recursive: true })
  .filter((f) => String(f).endsWith(".ts"))
  .map((f) => [f, readFileSync(`${dir}/${f}`, "utf8")] as const)
  .filter(([, src]) => /\brequire\(|from ["']node:/.test(src));

if (bad.length) {
  console.error("架构违规:渲染进程直接引用 Node API");
  for (const [f] of bad) console.error(" -", f);
  process.exit(1);
}
console.log("架构规则通过");

预期结果:

$ node --experimental-strip-types tools/check-arch-rules.ts
架构规则通过
# 故意在 renderer 里写一行 import fs from "node:fs" 后:
架构违规:渲染进程直接引用 Node API
 - main.ts
[exit code 1]

判据:这条规则能否在 CI 里以非零退出码挡住合并? 能 → 是规则;只能靠人 review → 是愿望。


4. harness 必须包含端到端层(§2)

层 是否在 harness 内 说明
单测 ✅ 快速反馈
组件/集成 ✅ 契约
端到端 ✅ 必须有 唯一能证明系统级行为
人工点击 ❌ 不能替代 不可重复、无断言

原文的 harness 定义是"可重复执行、带断言、失败即红"的集合;不是"一组手动步骤"。


5. E2E 最小集(E-S16-004)

场景 为什么必须有 断言点
主流程:登录 → 核心操作 → 结果可见 系统能不能用 终态数据 + 页面/接口返回
高价值异常:依赖失败时的降级 出故障时是否可用 响应时间、兜底值、错误码
边界数据:最大/空/重复提交 生产数据不听话 无 500、无脏数据、幂等
(可选)性能基线 防止"功能对但慢 10 倍" P95 < 阈值

数量控制:3–8 条。超过 10 条,维护成本会超过收益(B01 §3 的成本模型)。


6. 面向 agent(或新人)的错误消息(§3)

错误信息要让人/agent 能自己修,而不是只报"失败":

✗ e2e/export.spec.ts › 导出 100MB 文件
  期望: dist/report.zip 存在且 < 50MB
  实际: 文件缺失
  上游线索: 渲染进程传入 path="report.zip"(相对路径),预加载脚本要求绝对路径
  下一步: 在 renderer 中调用 path.resolve(dialogPath) 后再传给 preload
差的消息 好的消息
AssertionError: expected true to be true 期望/实际 + 上游线索 + 下一步动作
只贴堆栈 指出哪个契约被破坏

7. 常见误区

误区 纠正
"E2E 慢,用单测覆盖就行" 慢的是数量,不是必要性;用 3 条主干路径换系统级证据
"手动点一遍也算验证" 不可重复、无断言、无法回归
"有 E2E 就不用单测" 反过来也不行:E2E 定位成本高,分支仍归单测
"测试环境通过就等于生产通过" 配置差异要单独列(B01 §2 环境依赖)

8. 自测

  1. 你的项目现在有没有一条从入口到出口的自动化脚本?没有 → 先写主干那一条。
  2. 列出三条"如果坏了业务就停"的路径,它们是否都在 E2E 里?
  3. 你的一条架构规则能不能以非零退出码挡住合并?

9. 下一篇

S16-J01 · 链路追踪基础:Trace / Span / Parent Span —— 系统级证据的第二种形态:不是"跑通了",而是"跑的时候每一步花了多久、经过谁"。

S16-B04 · 端到端:跑通完整流程才算真正验证
https://www.clxhxhhr.top/posts/5409/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。