工程上最危险的不是完全不可用,而是在理想环境里正常、进入真实网络和真实数据量后悄悄失去边界。 示例测试验证已知故事,属性测试探索事件排列。模型定义任意时刻最多一个活跃会话、终态不可逆、确认字节不超过文件大小等不变量。
测试要把状态机、故障注入和真实浏览器组合起来。确定性用例守住已知契约,随机时序寻找竞态,失败 seed 和两端轨迹必须保存成永久回归。
工程边界与取舍
实现之前先列出不可违反的不变量,再为性能与体验留出调节参数。参数可以灰度,身份、权限和终态规则不能在运行时随意漂移。
- 生成 command、timeout、duplicate、refresh 与 network change,模型和实现同时执行;失败 seed 进入回归库,shrinker 保留最短触发序列。
- 先定义正常、降级、取消和失败四类终态,再让界面、存储与指标消费同一状态。
- 上线参数必须有保守默认值、服务端上限和灰度开关,不能把浏览器传来的数字直接当作资源预算。
“协议属性测试:让随机事件序列寻找人想不到的状态组合”的交付标准是正常路径可用、异常路径收敛、资源有界,并且用户能理解系统为何采用当前状态。 这样得到的不是演示代码,而是能解释、能降级、能回滚的生产能力。
生产环境会怎样出错
不要把异常路径理解成弹一次提示。它还包括在途工作如何停、对端如何获知、残留数据如何处置,以及下一次操作是否会继承旧状态。
- 完全无约束随机只产生大量无意义事件;只断言“不抛异常”又会漏掉双方永久分歧等逻辑错误。
- 刷新或网络切换同时触发两条恢复路径,重复副作用被误当成两次真实用户操作。
- 降级路径从未压测,主路径故障时所有流量同时进入更慢、更昂贵的后备方案。
把测试跑成闭环
验证时同时观察两端状态、持久化记录和可观测指标。单看某个按钮或一次接口响应,无法证明整个闭环成立。
- 运行至少十万序列并故意注入一个旧 answer 覆盖缺陷,确认工具能发现、缩小并稳定重放到最小反例。
- 用乱序、重复和延迟消息驱动状态机,确认旧版本被丢弃且显式停止不会被自动恢复覆盖。
- 发布前记录成功率、p50/p95/p99 延迟、错误分类和资源高水位,并为回退条件设定明确阈值。
当实现能够安全降级、重复执行不产生额外副作用、故障指标早于投诉出现时,这项能力才算具备长期维护价值。