客户现场跑通一次,只是一个没人能重跑的测试
谷歌SRE一书说没测过就当它坏了;真正的交接要留下测试、可度量的验收标准和运行手册,让客户团队敢改代码。
要点速览
- Google 的 SRE 书指出,测试通过不能证明系统可靠,测试失败却能证明系统不可靠。所以“在客户那边能跑”是很弱的证据。
- FDE 的定制代码只为一个客户而写,常常没有测试。而以后要改这些代码的,是客户团队的人。
- 交接时应包括:用数字定义的“可用”标准、每个行为对应的测试、每个缺陷对应的回归测试,以及附带复现用例的上游 PR。
Google 的《Site Reliability Engineering》一书中,讲可靠性测试的那一章开头有一句简短的题记:没试过的东西,就当它是坏的。几段之后,书里说得更进一步:测试通过不一定能证明系统可靠,但测试失败通常能证明系统不可靠。
在给客户发消息说“搞定了,现场已经跑起来了”之前,先想想这两句话。仔细看,在客户线上系统里顺利跑一次,不过是通过了一个测试。这个测试没人写下来,也没人能再跑一遍。
这一点之所以重要,是因为每个前线部署工程师(FDE)项目最后都要交接。Educative 讲 AI 系统 FDE 的课程里说,客户团队无法运维自己不理解的东西,也无法维护只为 FDE 设计的东西。从交接那天起,问题就从“能不能用?”变成了“改起来安不安全?”
顺利跑一次能证明什么?
看一个典型场景。你给客户写了一个脚本:从旧系统读取订单导出文件,统一日期和货币单位的格式,再把数据导入新的数据仓库。脚本在最近三天的数据上运行顺利,客户看了看仪表盘,点了点头。
这次运行证明了三件事:这三天的文件格式符合你的假设,访问权限配置正确,数据管道的每一步都没有失败。
至于某个分店导出的日期换了格式、某一行缺了客户 ID,或者下个月客户的工程师改了某个列名,会发生什么,这次运行什么也说明不了。这些情况都还没发生过,顺利运行自然无法提供任何信息。
公平地说,在真实数据上运行必不可少。PostHog 介绍 FDE 岗位的文章写道,FDE 会一直和客户一起推进,直到客户在真实数据上看到真实结果。但这是验收的条件,不是系统经得起变更的证据。
SRE 书点明了其中的差别:每个在变更前后都能通过的测试,都会减少分析人员需要考虑的不确定性。关键在于“前后”二字。现场的那次顺利运行没有“后”,因为代码改动时没人会再跑一遍。
为什么 FDE 的代码常常没有测试?
主要原因在于工作的组织方式。只为一个客户写代码,又要赶在演示前出结果,测试最容易被砍掉。
这套理由听上去很合理:代码只在一个地方用,出了问题你就在旁边,随时能修。可这套理由只在你离开之前成立。
Second File 在 Substack 上一篇讲 Field-to-Product 模式的文章里提醒了两件事:只存在于某个客户账户里的定制代码,以及成为单点故障的“英雄”工程师。没有测试的代码恰恰会把你变成这种英雄,因为只有你知道它该做什么、不该做什么。
接手代码的人来买单
《Software Engineering at Google》写道,测试软件还有一个同样重要的理由:保住修改软件的能力。对即将交接的项目来说,后果很直接。没有测试的代码仍然可以改,但对客户团队来说,每次修改都是一场赌博。
而且代价会随时间增长。同一本书说,缺陷在开发生命周期中发现得越晚,修复成本越高,很多情况下呈指数级增长。对 FDE 的代码而言,最晚的时刻就是作者已经转去别的项目,缺陷才在客户的生产环境中暴露出来。
测试还能做到书面文档很少做好的一件事。一个只检查单一行为的简短测试,能告诉客户团队你原本打算让脚本如何处理没有客户 ID 的行。它比任何 wiki 页面都可靠,因为它会运行。
交接证据是什么样的?
如果顺利跑一次还不够,那什么才够?下表把顺利运行放在第一行作为基准,再列出另外五类证据。每类证据回答的问题不同,彼此不能替代。
| 证据 | 能证明 | 不能证明 | 谁最需要 |
|---|---|---|---|
| 在客户现场顺利运行一次 | 代码在当天的数据和配置下没有出错 | 代码能应对新数据、新配置或新改动 | 演示时的客户 |
| 项目开始时约定的、用数字定义的“可用”标准 | 双方对成功的含义达成一致 | 代码是否易于维护 | 客户方的项目负责人 |
| 自动化测试,每个测试只验证一个行为 | 预期行为在每次修改后依然成立 | 代码满足客户的业务目标 | 修改代码时的客户工程师 |
| 根据现场缺陷编写的回归测试 | 已知缺陷不会再出现 | 还没人遇到过的缺陷 | 在各个缺陷所在位置修改代码的人 |
| 定时运行的生产环境测试 | 线上系统长期保持健康 | 某次具体改动是否破坏了某个行为 | 运维团队 |
| 附带复现用例的上游 PR | 修复在核心产品中有了归宿 | 客户剩余的定制代码是否可靠 | 产品团队 |
Truong Phung 在 dev.to 上发表的一份 FDE 实践手册用一个对比概括了这种差别:顾问留下的是文档,FDE 留下的是一个运行中的系统,以及组织运维这个系统的能力。表中第一行之下的五类证据,就是这种能力,而且是客户团队可以自行检验的形式。
这份手册还建议,从一开始就把要留下的交付物写进项目定义里,包括评测、运维手册和对客户方负责人的培训,而不是拖到最后。作者提醒,没有这些,系统会在你离开后 90 天内逐渐腐化。
把现场的每个缺陷都变成测试
给老代码补齐完整的测试套件并非必需。最朴素的起点,是把现场发现的每个缺陷都记录成一个测试用例。对 FDE 来说,这几乎不增加成本,因为修缺陷时,引发缺陷的输入就在手边。
回到那个订单脚本。假设第二周某个分店发来的文件里,日期按日-月-年书写,而脚本把它读成了月-日-年。
你修好了它,再多花十分钟写一个测试,用的就是那三行数据,检查日期是否被正确解析。从此以后,任何客户工程师改动日期解析函数时,只要再次弄坏这个场景,测试马上就会失败。
下一步是把值得保留的东西移进产品。Field-to-Product 那篇文章用一句话概括了泛化这一步:把抽象和测试推到上游,淘汰本地补丁。
上面的日期解析缺陷就是很好的候选。如果产品本身有导入功能,这个测试就应该放进产品仓库,而不只是留在某个客户的定制目录里。
决定成败的是时机。这些工作大多必须在项目第一周就开始,而不是最后一周,原因在于晚写的测试实际上在做什么。
最后一周写的测试在检查什么?
最常见的错误是以为有了生产环境检查就够了。生产环境测试必不可少,但它只能说明系统依然健康,无法告诉你上一次改动破坏了哪个行为。
更隐蔽的错误是把测试都挤到最后一周。这时写的测试往往只是记录代码当前的行为。freeCodeCamp 的一篇教程说得很明白:这类测试并不能说明现有行为是正确的;作者写道,自己只是在记录行为,并不假装它是对的。
重构遗留代码时,这种技巧很有用。但如果交出去的测试套件全是这种测试,你就是把自己的错误冻结起来,当作预期行为交给客户团队。在你还在问客户“没有 ID 的行该怎么处理?”时就写下的测试,记录的是意图,而不是现状。
另一个陷阱是写一个巨大的测试,从输入文件一路检查到仪表盘。它一旦变红,客户工程师根本看不出是哪个行为坏了。最后一个陷阱是在现场修了缺陷却不留测试,还把修复一直放在定制分支里。缺陷可能卷土重来,核心产品也永远不会知道它的存在。
招聘经理想看到什么?
在简历上,“为客户 X 部署了一条数据管道”的分量不比一次顺利运行更重。“交接时为现场发现的每个缺陷都附上了回归测试;之后的修复由客户团队独立上线”说明的要多得多。
面试时,要准备好讲清一个具体缺陷:你是怎么复现的,测试长什么样,这个测试现在放在哪个仓库里。
现场顺利运行能帮你拿到验收签字。交接做得好不好,要等到客户团队第一次修改代码、而且不用打电话找你的时候,才见分晓。
这篇文章对你有帮助吗?
感谢你的反馈!
7 个信源
- Testing for Reliability (Site Reliability Engineering, Ch. 17)
- Testing Overview (Software Engineering at Google, Ch. 11)
- The Forward-Deployed Engineer Playbook (DEV Community, Truong Phung) · 2026-06-21
- Field‑to‑Product: an operating system for Forward‑Deployed Engineers · 2025-09-14
- WTF is a forward deployed engineer? (and why everyone is hiring them) · 2026-02-11
- How to Build Characterization Tests Before Refactoring Legacy Code · 2026-08-31
- The Project Handoff (Forward Deployed Engineer for AI Systems, Educative)