菜单

跨国家扩展测试数据:不变量与例外清单

从几个国家扩到几十个国家,靠加数据是不够的,得先分清哪些规则在所有国家和地区都成立,哪些本来就是例外。本文用不变量与例外清单来组织这件事。

发布于

  • 扩展
  • 不变量

跨国家扩展测试数据听起来只是把样本从几个加到几十个,实际做起来会发现成本不在数据量,而在规则。每新增一个国家和地区,都可能带来一条新的例外:没有邮编、行政区层级更浅、编码只在部分体系里有值。没有事先分好的不变量与例外清单,扩展就会变成一次次的临时补丁。

从几个国家扩到几十个,难在哪?

难点有三个层次,成本依次递增。

第一层是数据量:更多的地址、更多的名称、更多的行政区。这一层是体力活,靠收集与整理就能解决。

第二层是组合:国家和地区与语言、与支付方式、与配送方式相乘,组合增长远快于样本数增长。

第三层是规则分歧:原本在一两个国家和地区上成立的假设,到第十个就不成立了。这一层最贵,因为它会影响已经写好的逻辑,而不是只增加数据。

多数团队在第二层就开始吃力,真正卡住的是第三层。而第三层恰恰是可以提前准备的,前提是先有一份不变量与例外清单。

扩展的前提是国家集合本身稳定;这份集合一旦反复变动,前面所有的断言都要跟着重算。

不变量:在所有国家和地区都成立的规则

不变量是那些无论扩展到多少个国家和地区都不需要改的规则。它们通常很朴素,例如:

  • 每个条目都有一个稳定的内部标识。
  • 一条地址至少属于一个国家和地区。
  • 每个条目的状态是有限取值之一。
  • 未选择的条目不应被当成有效值写入。

不变量的价值在于:它们可以用属性方式测试——不需要枚举输入,只需要断言「无论哪一条数据,这个性质都成立」。这类断言写一次就能覆盖全部数据,扩展时零成本。

不变量还有一个作用是止损:当某条断言在新数据上失败时,你立刻知道要么是数据错了,要么是这条不变量定得太宽,而不必在两者之间反复猜。

写不变量时要克制。凡是需要举例才能说清的,多半不是不变量而是常见情况;把它硬当成不变量,第一次遇到例外就会全线报错,反而会让人不再相信这套断言。

不变量与例外合起来才描述得清数据,而覆盖率清单正好是记录两者边界的地方,见国家数据覆盖率清单。

例外清单应该记什么?

例外清单要记的是「哪些国家和地区不遵循哪一条常见规则」,而不是「有哪些奇怪的国家和地区」。

每一条例外至少包含四项:涉及哪个条目、偏离了哪一条规则、为什么偏离、以及从什么时候起有效。

只写条目名的清单没有用,因为它不告诉你该跳过哪一步校验;只写规则名的清单也没有用,因为执行时不知道该对谁网开一面。

例外还需要有生命周期。如果某条例外对应的原因消失了,它应该被删除,而不是永远留着。清单如果没有清理机制,只会在几年后变成谁也不敢动的历史遗迹。

还有一个反直觉的建议:例外清单应该尽量短。例外太多的系统,通常说明不变量定错了——把某条常见情况误当成了普遍规律。

数据驱动与代码分支怎么选?

面对国别差异,有两种写法,各有适用场合。

代码分支是把差异写进逻辑:如果属于某类国家和地区,就走另一套流程。它直观、调试方便,适合数量少且几乎不会变的差异。

数据驱动是把差异写成配置:规则、字段集合、必填性都从数据里读。它扩展成本低,新增一个国家和地区通常不需要改代码,代价是配置本身也会变得复杂,而且问题会从编译期推迟到运行期。

实践中的分界大致是:结构性的、几乎不动的差异用分支;随国家和地区数量增长的差异用数据驱动。

有一条硬性判据很有用:新增一个国家和地区时要不要改代码。如果每次都要改,说明这部分应该被数据化;如果几乎不用改,说明当前的选择是对的。校验规则本身的组织方式在跨主题里有更一般的讨论,见号码校验是怎么工作的。

扩展时先加国家还是先加字段?

这个顺序会显著影响返工量。

先加国家和地区的做法能快速暴露规则分歧,适合探索阶段:你会在很短的时间里知道哪些假设不成立。

先加字段的做法能把结构先搭好,适合结构已经清楚、只是要补维度的情况:边界清晰之后,补字段是线性的工作。

如果两者都不确定,建议小步交替:一次只加少量国家和地区,同时只加少量字段,观察哪一侧先出问题。这样每一轮的结论都能被解释,而不是在一堆同时变化的条件里找原因。

无论哪种顺序,都要给每一轮留一份记录:这一轮加了什么、发现了哪条新例外、哪条旧例外被删掉了。这些记录本身就是最重要的产出,因为下一轮要接着用。

给开发者:让新增一条数据不需要改代码

把扩展成本压下来的关键,是让新增一条数据成为纯数据操作。

条目要有稳定的内部标识,外部编码作为属性,这样编码体系变化时数据结构不用动。

规则要能按属性组合出来,而不是按条目名列举。必填、格式、可选值都应当是由属性推导的结果。

例外的表达要有位置:它可以是一条带生效时间的记录,也可以是给条目打的标记,但不能是散落在逻辑里的条件判断。

变化要能被观测:新增一条数据之后,能用一次查询确认它落进了哪些规则分支、命中了哪些例外。

做到这几点,扩展就从「改代码加测试」变成「加数据跑断言」。而数据本身也会过期,这套时间维度上的维护见国家数据新鲜度。

要对照着看国家和地区条目实际有哪些属性,国家和地区总览是一个现成的入口。

下一步

先把现有断言按不变量与例外分一遍:哪些是无论加多少国家和地区都成立的,哪些只是当前样本凑巧成立的。再把例外整理成带生效时间的清单,删掉已经没有原因的那些。

做完这一步,下一轮扩展就会从「又踩到一个坑」变成「又验证了一条不变量」。

文中的不变量条目与例外清单都是为演示组织方式而写的示例结构,不代表任何真实系统的断言全集,也不构成对任何具体校验实现的描述。

继续阅读

各国地址与身份数据格式相关文章