需要一百个测试账号的时候,最常见的做法有两种:打开注册页填一百遍,或者写个循环随机生成。前一种不可复现,后一种会在第三次重跑时长出三百个重复用户。批量造号是数据工程问题,不是体力问题。
这篇文章讲三件事:怎么组织数据让它可复现,怎么选输出格式,以及怎么让这批数据可以被反复重跑。
先分清预发环境与生产
批量造账号只应当在预发、演练或专用的测试环境里做。生产环境里的测试账号是一项长期负担:它们会出现在报表、用户统计和真实客户列表里,混进去容易,清理干净很难,而且一旦有人误以为它们是真实用户,后续的判断都会出错。
如果某条流程只能在生产验证(有些第三方服务确实如此),那正确的做法是限定范围:用明确的命名规则、单独标记这些账号、记录创建它们用到的标识,做到随时能精确删除。绝不要在共享的生产环境里「先造一批用着」。
为什么要用固定标识代替随机值?
可复现的核心是:给定同一个标识,生成结果完全相同。
本站的几个工具共用一个身份标识。同一个标识配上同一个国家和性别,永远产出同一条记录,姓名、性别、生日、地址、邮编、证件号、手机号都出自同一条数据。这意味着你可以把「一个标识」当成一条账号的完整档案,而不是把十几个字段分别抄下来再人工对齐。
批量造号时,标识的命名要满足两个条件:稳定,以及看名字就知道它是干什么的。常见写法是加一个业务前缀,再接一个固定宽度的序号,前缀表明这批数据属于哪个环境或哪个测试主题,序号决定它的顺序。
不要用行号当作标识。行号看起来等价,但只要你重排一次导出顺序、删掉中间某一行,整批数据的对应关系就全变了,而且变化是静默的。标识是数据的一部分,应当和生成结果一起写进文件。
国家也要固定。同一批标识配上不同的国家,得到的是完全不同的记录,所以国家必须显式写在配置里,而不是依赖运行时默认值。需要按国家分批时,就用「标识段加国家」的组合,例如美国用户跑一遍、德国用户跑一遍,两次之间互不影响。可复现本身的意义和可复现的测试数据里讲的是同一个:失败能被别人重建,改动的影响范围能被算出来。
四种输出格式各适合谁
批量生成的输出格式决定了这些数据能怎么用,选错会浪费很多时间。
第一种是逗号分隔的表格文件。最适合导入后台管理工具、用电子表格审阅,以及交给不写代码的同事确认数据。要点是字段里逗号、引号和换行的转义,以及编码。用表格软件打开无字节序标记的文本文件有时会显示乱码,需要在导出时定好编码,不要等到别人打开发现是乱码再回头改。
第二种是嵌套的文本对象。适合一个用户里带地址对象和证件对象这类结构,最适合作为自动化测试的固定装置,或者通过接口一次性灌入。缺点是文件体积大,数据量大时会占用较多内存。
第三种是每行一个独立文本对象的行式文件。它把嵌套对象的表达能力和行式文件的流式处理结合起来:可以边生成边追加、边读边导入,某一行写坏了不会毁掉整个文件,导入失败时能精确定位到行号。批量灌数据时这是最省事的格式。
第四种是数据库语句。导入最快,适合直接写进数据库或放进种子脚本。代价是转义要自己负责,字符串里的单引号必须处理,日期和布尔值要按目标数据库的写法。另一条纪律是:生成的语句只能用于测试环境,并且要带上幂等子句。
四种格式可以同时产出。同一批标识导成表格给人看、导成行式文件给导入脚本用、导成语句给初始化流程用,三者内容一致,因为源头是同一份数据。
| 格式 | 最适合谁 | 主要代价 |
|---|---|---|
| 逗号分隔表格 | 人工审阅、后台导入 | 转义与编码容易出错 |
| 嵌套文本对象 | 固定装置、接口灌入 | 体积大、占内存 |
| 行式文本对象 | 批量流式导入 | 需要按行解析 |
| 数据库语句 | 直接落库、初始化 | 转义与方言要自己负责 |
怎么让重跑是幂等的?
幂等的定义很直白:同一个脚本跑一遍和跑五遍,数据库里的最终状态相同。
首先,主键和唯一键必须由标识推导,而不是由数据库生成。账号标识、登录邮箱、用户名都应当能由标识唯一确定。这样第二次运行时,冲突会发生在唯一约束上,而不是产生一条新记录。
其次,写入使用更新或忽略的语义。把数据当作「这些标识对应的记录应当长这样」来声明,而不是「请插入这些记录」。多数数据库都支持在冲突时更新或忽略,导出语句时可以用这一条来实现。
第三,给出一个稳定的清空方式。种子脚本至少要有两个模式:写入与清理。清理的依据是标识的前缀,而不是清空整张表。在共享的预发环境里,清空用户表会毁掉别人的工作。把本批标识的清单存成文件,清理时按清单删除,这样做的另一个好处是你能随时说清楚这批数据一共有多少条、分别叫什么。
有一个反直觉但值得遵守的做法:即使脚本已经幂等,也不要在同一次运行里写多张关联表却不使用事务。地址表、证件表、支付方式表如果分三次写入,中途失败就会留下半条记录。要么包在一个事务里,要么先写主表再补从表,并且让补写步骤本身也是幂等的。
为什么绝不要用真实个人信息?
这一条没有例外。
不要用同事、家人、客户的真实姓名和手机号,即使对方口头同意;不要用生产库里导出的用户数据,哪怕是脱敏过的;不要用自己真实的证件号码或邮箱来「测试一下」。理由不只是隐私:真实数据写进测试库、日志、截图和缺陷报告之后,就再也要不回来了,而你没有能力保证这些地方都受控。
合成数据在测试效果上并不差,有些地方反而更好。证件号的校验位算法是公开的,工具可以精确构造出校验位正确的号码,从而覆盖官方校验路径。真实号码的分布很窄,反而很难凑出边界组合。
邮箱同样不要用真实的。测试账号的登录邮箱应当落在一个保留给示例用途的域名上,而不是某位同事的真实邮箱;后者会把测试邮件和通知真正投递出去,收件人还以为自己收到了什么重要通知。
批量造号往往还要造地址和公司信息。身份信息生成器给出与标识一致的证件、生日与姓名,地址生成工具提供格式合规的地址与邮编,公司信息可以生成与同一个标识一致的企业档案。它们的作用是让测试路径走得通,不是让数据变成真的。
常见问题
测试账号要不要标记出来?
要,而且要能从数据里直接看出来。命名前缀、邮箱域名,以及在用户表上带一个标记列,三种方式都可以,但至少要保证一点:任何人都能一眼分辨这批记录是种子数据,不需要先去查文档。
换一批标识会怎样?
所有内容都会变,因为记录是由标识推导出来的。这是设计上想要的行为:需要一批新样本时换标识前缀,改动只有一行;需要稳定样本时就不要动标识。唯一要避免的是「部分标识换、部分不换」,那会让新旧数据混在一起,谁也说不清哪些属于同一批。
大批量数据要不要提交到仓库?
不要。数据量一大就会让仓库膨胀,改动记录也没法看。提交标识列表和生成脚本就够了,数据在需要时现生成;如果测试依赖某个特定的期望值,把那一小份输出作为快照存下来做比对。
这样造出来的账号能测什么?
注册与登录、资料页与地址管理、证件格式校验、权限与角色、列表分页与搜索、批量导出,以及数据迁移。它们测不了真实用户的分布特征,也测不了真实业务量下的性能,那属于另一类测试,不应该靠把种子数据放大到几十万条来解决。
本文面向测试与预发环境的工程实践,不构成对任何注册流程、身份核验制度或平台规则的规避建议;批量造出的账号只能用于你获得授权的测试环境,任何时候都不要把它们当作真实用户使用。