这周在处理一个很典型的需求单:编号 10001,标题写着“需求管理新增字段【ADB 模块】、【YUNTI 模块】需求文档(测试文档)”。先给结论:这类“就是加几个字段”的需求,写起来远比看上去复杂。加字段不只是数据库里多一列,它牵扯到前端表单、列表展示、详情页、导出模板、接口出入参、数据字典、历史数据回填、权限控制,还要配一套能验证这些链路的测试用例。这篇文章把我处理这个需求的全过程拆开讲,从需求澄清、字段设计,到测试文档编写、评审应对和上线自检,适合正在做需求管理、配置管理和测试设计的朋友参考。
1. 接到需求单,先别急着写字段表:三个问题问清楚
1.1 ADB 模块和 YUNTI 模块到底在解决什么场景
我拿到这个单子的时候,第一反应不是去画字段,而是先把两个模块在现有系统里的位置彻底弄清楚。ADB 模块在我们这套需求管理平台里承担业务接入申请记录的流转,YUNTI 模块负责资源变更记录的登记和追踪。为了不把原始业务细节铺得太开,下面统一用这套代称来讲。
这两个模块有一个共性:现有的核心字段只覆盖了“记录本身是什么”,却没有覆盖“这条记录当前处于什么状态、由谁负责、预计什么时候处理完”。比如 ADB 模块的列表能看出申请内容,但看不出渠道来源和优先级,业务方每天打开列表,只能再点进详情看流水日志去猜哪一个该先处理。YUNTI 模块也是类似的别扭,变更单能看出来改了什么,但看不出负责人是谁、这个变更来自人工提交还是接口触发,导致出问题的时候找不到人。
所以新增字段在设计层面本质上不是“拍脑袋加几列”,而是在补业务流程里的信息断点。需求澄清的第一步,就是把这种“不好用”的痛点和字段缺口对齐。
1.2 “测试文档”四个字意味着什么
需求文档后面挂着“测试文档”四个字,这不是可有可无的后缀。结合需求管理平台的分类习惯,这种文档要同时承担两个职责:第一是把需求本身描述清楚,第二是让测试同事能直接照着设计用例。也就是说,文档里的每一条字段描述,都要能翻译成一句“如果怎么操作,应该看到什么结果”的预期。
这也解释了为什么同样一份文档,有人觉得写得够详细,有人却觉得没法下手。问题通常出在字段描述只写了“新增什么”,没写“在哪里展示、能不能为空、对历史数据有没有影响、错误时怎么提示”。把这些问题补上,需求文档才真正具备测试属性,也才对得起“测试文档”这个类型。
1.3 需求澄清会怎么开才不会白开
需求澄清会不要开成“大家一起看文档”。我一般把问题按下面几个维度列成清单,逐条过:
- 字段来源:字段由谁新增、谁修改、谁查看,操作权限分别落在哪些角色上。
- 界面位置:字段出现在列表、详情、表单哪几个地方,新增、编辑、查看时是否一致。
- 约束条件:是否必填、是否唯一、是否参与排序、是否允许为空。
- 字典范围:可选值的来源是固定枚举、动态字典还是外部接口。
- 数据影响:历史数据要不要回填,老数据不适用新字段时怎么兜底。
- 导出需求:导出模板是否增加列,列名和列宽怎么定,导出格式与页面展示是否一致。
我会把这些问题在会前发给相关角色,会上不是问“有没有问题”,而是问“每个字段在这六个维度分别选什么”。这样开会效率会高很多,开完就能形成一页需求澄清记录,作为后期字段设计的输入,而不是开完会脑子里还是糊的。
2. ADB 与 YUNTI 的字段清单:从业务规则到字段属性的一次推演
2.1 字段命名、类型、取值范围怎么定
字段设计一定要先定规范再填内容。我们这里的约定是:内部字段名统一用英文驼峰,必须带模块前缀,避免将来和其他模块的同名字段在接口层撞车。下面这张表是我这次沉淀出来的第一版字段清单,字段名和枚举值都做了脱敏,但设计思路可以直接复用:
| 模块 | 字段名 | 中文含义 | 数据类型 | 是否必填 | 默认值 | 字典/说明 |
|---|---|---|---|---|---|---|
| ADB | adb_channel | 渠道来源 | varchar(32) | 是 | 无 | 枚举:self、partner、other |
| ADB | adb_priority | 优先级 | tinyint | 是 | 1 | 1低、2中、3高,参与列表排序 |
| ADB | adb_estimated_time | 预计完成时间 | datetime | 否 | 无 | 精确到分钟,详情页展示 |
| ADB | adb_remark | 备注 | varchar(500) | 否 | 空串 | 详情页展示,不参与筛选 |
| YUNTI | yunti_owner | 负责人 | varchar(64) | 是 | 空串 | 存人员工号,展示时翻译为姓名 |
| YUNTI | yunti_source_type | 来源类型 | varchar(32) | 是 | manual | 枚举:manual、api、migrate |
| YUNTI | yunti_status | 状态 | varchar(20) | 是 | pending | 枚举:pending、processing、done、rejected |
| YUNTI | yunti_effective_date | 生效日期 | date | 否 | 无 | 只精确到天,不参与时间计算 |
字段表谁都会列,难点在确定每一项背后的理由。我挑三个容易出问题的字段展开说。
第一个是 adb_priority。业务方最开始提的是“优先级用一个文本备注就行”,但后来发现列表要按照优先级排序,文本字段排序会出来字典序,3会排在10前面,而且“高”“中”“低”这种中文文本在不同终端上的排序规则还容易不一致。最后改成 tinyint,配合映射关系展示“低中高”,排序和展示彻底解耦。
第二个是 yunti_owner。字段如果直接存姓名,会面临人员离职、改名、重复名的问题。我们权限体系里本来就有统一的人员接口,所以最终落库存工号,前端展示时再翻译成姓名。这样权限过滤、待办推送、后续统计都能用同一个标识,不会出现“张三”和“zhangsan”对不上的尴尬。
第三个是 yunti_effective_date。日期和时间是两个概念,很多人会顺手用 datetime,但这里的业务语义只到“哪一天生效”,用 datetime 反而会引入时区、跨天这些没必要的复杂度。所以我明确用 date,存储、查询、展示都不需要额外转换。
字段长度也一样。比如 adb_channel 设 varchar(32),不是因为渠道名最多 32 个字符,而是因为字典里的枚举值最长是 16,预留一倍是为了以后增加枚举项时不用马上改表结构。长度不是拍脑袋写的,要有余地。
2.2 历史数据与兼容性:最容易忽略的“半路出家”问题
新增字段时大家都盯着新数据,却很容易忽略老数据。两个模块在线上已经跑了大半年,存量记录不会自动带上新字段。处理原则是这样的:
- 字段允许为空,存量记录留空即可,但前端展示要定义“空值显示什么”,一般显示短横线。
- 字段不允许为空,必须提供一个回填方案。比如 adb_priority 存量统一回填为 1,yunti_status 按流程节点反推当前状态。
- 字段要参与统计,回填值必须经过业务确认,不能技术团队自己拍板。
数据库变更我一般会写成可重复执行的迁移脚本,核心部分长这样:
ALTER TABLE adb_record ADD COLUMN adb_channel varchar(32) NOT NULL DEFAULT 'self' COMMENT '渠道来源'; ALTER TABLE adb_record ADD COLUMN adb_priority tinyint NOT NULL DEFAULT 1 COMMENT '优先级 1低 2中 3高'; ALTER TABLE adb_record ADD COLUMN adb_estimated_time datetime NULL COMMENT '预计完成时间'; ALTER TABLE yunti_record ADD COLUMN yunti_owner varchar(64) NOT NULL DEFAULT '' COMMENT '负责人工号';注意,这里用了 NOT NULL 和 DEFAULT,是为了保证存量行读取时不会出现 NULL。类似的做法在测试文档里也要体现一条:历史数据回填后,列表页、详情页、导出文件三个地方展示的结果要一致。否则很容易出现数据库有值,导出却还是空的情况。
3. 测试文档怎么写:字段需求转成验收用例的完整拆解
3.1 每条需求必须能对应到测试点
需求文档要变成测试文档,最有效的方法是在文档里同时维护一张“需求-用例映射表”。我习惯用一个编号体系,需求条目是 REQ-001、REQ-002 这种,测试用例是 TC-001、TC-002 这种,两者一一挂钩。
对应关系如下:
| 需求条目 | 需求内容 | 对应用例范围 | 关键预期 |
|---|---|---|---|
| REQ-001 | ADB模块新增 adb_channel 字段 | TC-001~TC-004 | 必填校验、字典值、非法值、保存后展示 |
| REQ-002 | ADB模块新增 adb_priority 字段 | TC-005~TC-008 | 默认值、排序、范围校验、导出展示 |
| REQ-003 | YUNTI模块新增 yunti_status 状态字段 | TC-009~TC-012 | 状态流转、权限可见、历史数据回填 |
这样做的好处是,评审的时候不用争论“这里该测不该测”,而是直接对着表说这条用例的预期对不对。文档挂了“测试文档”这个属性,就该早一点把测试视角拉进需求阶段,而不是等研发做完再补测试用例,那样既被动又容易漏。
3.2 字段测试的边界值和异常场景
字段级用例最容易写漏的是边界和异常。拿 adb_priority 举例,正常用例只覆盖 1、2、3,但真正上线前我会补这么几个:
- 提交 0 和 4,验证是否被校验拦截。
- 提交空字符串和 null,验证必填提示是否准确。
- 提交小数、负数、超长字符串,验证接口是否返回明确的错误码。
- 列表按优先级排序时,3 优先于 2,2 优先于 1,而不是按创建时间排。
- 导出模板里优先级显示为“低中高”,不是数字 1、2、3。
yunti_owner 这类人员字段也要测:输入不存在的工号、输入离职人员工号、批量导入时负责人字段为空,以及负责人显示时是否和人员接口的姓名一致。这些在平时回归里属于高频问题,提前写进用例,能省掉很多线上工单。
3.3 页面、接口、数据库三层验证
字段改动很少只落在一层。前端表单、后端接口、数据库表三处都要能对上,否则就会出现“页面能填,接口不存,数据库为空”这种问题。联调时我通常按三层分别确认:
前端层:表单校验规则、提示文案、详情展示、列表列头与宽度、筛选条件里是否增加了新字段,以及空值状态下页面的展示是否符合预期。
接口层:创建接口、更新接口、详情接口、列表接口的出入参是否包含新字段,字段名大小写是否正确,老客户端不传新字段时能不能正常兼容。字段变更导致的接口报错,错误信息里要能看出是哪个字段出了问题。
数据层:新增记录后数据库字段是否正确落库,历史数据回填是否执行成功,字段值是否符合字典约束,是否存在超长截断。
3.4 测试数据准备与回归范围圈定
准备测试数据时,不能只准备一条“完美数据”。我一般至少准备三批:一批新数据、一批旧数据、一批边界数据。旧数据用于验证回填逻辑,边界数据用于验证校验逻辑,新数据用于覆盖正常主流程。
回归范围也不是只跑新增字段相关页面,而是要带上列表页、详情页、导出、权限过滤、排序这几条链路,因为它们都可能在同一个查询里用到新字段。尤其是导出,很多线上问题都出在导出模板漏加列,或者列头错位,这类问题用自动化用例不容易发现,测试文档里必须显式写出来。
4. 评审会上最容易被挑战的四个点以及怎么回应
4.1 “这个字段为什么要叫这个名字”
这个问题几乎每次都会有人问。应对的核心不是临场解释,而是提前把命名规范写进文档。我们这边的规矩是:内部字段名用英文驼峰,带模块前缀,展示名称单独配置。比如 adb_priority 展示为“优先级”,如果业务方坚持要叫“重要程度”,那是字典值的调整,不影响字段名。
刚开始带需求评审的时候,我也被问住过,后来明白一个道理:字段名不是给某一个人看的,是给所有上下游系统看的。一旦定了,接口、数据库、报表、权限配置都要沿用,改名成本极高。所以评审会上看到命名分歧,不要急着争论“好不好看”,而是先确认这套命名会不会影响已确定的接口协议和数据字典。
4.2 “那个字段以后可能改成多选”
评审会里经常听到“现在单选用着,以后可能会变成多选”。我的处理方式是先问清楚变化周期。如果三个月内确实要改,我会在字段设计上预留空间,比如 yunti_source_type 直接用逗号分隔存字符串,或者提前用 JSON 数组,避免后面做结构迁移;如果只是“未来可能”,就不要为不确定的需求增加复杂度。
凡是临时改类型的需求,一定要评估历史数据和新老版本兼容,并在文档里注明变更影响。单改多最大的坑在于存量数据:存量值是单个字符串,改成多选后历史数据显示成什么,需要提前定义清楚,否则上线后详情页会展示出很难看的格式。
4.3 “为什么新增字段要动权限”
yunti_owner 和状态这类字段天然涉及数据敏感度,不是所有角色都能看。需求文档里要单独画一个权限矩阵:哪些角色可读、哪些角色可写、哪些字段列表页可见、哪些字段详情页才显示。不写这个,上线后很容易被安全同事打回。
权限矩阵示例:
| 字段 | 管理员 | 业务操作员 | 只读人员 |
|---|---|---|---|
| yunti_owner | 读+写 | 读+写 | 只读 |
| yunti_status | 读+写 | 读+写 | 只读 |
| adb_priority | 读+写 | 读 | 只读 |
还可以进一步定义:字段是否进入列表查询条件。比如 adb_estimated_time 只有详情页可见,不进列表,不参与筛选,这样权限、性能、展示三个问题的边界都清楚了。
4.4 评审记录与变更控制
评审会上被挑战是好事,说明大家认真看了。但文档不能在评审后七改八改,尤其是字段类型这种一旦落库就很难回头的决定。我会准备一个版本记录表,记录版本号、修改人、修改内容、修改原因和确认人。任何字段名、类型、字典值的变更,都要重新走一次相关角色确认,不能私下在群里说一句“改一下吧”就直接改。
关于“测试文档”这个类型,评审记录里还要专门写清楚测试范围。哪些字段纳入本次测试,哪些字段只是预留接口不落库,哪些字段会影响历史数据展示,这三类事件在评审表里分开列,后面测试执行时才不会有人拿着预留字段当 bug 提。
5. 从评审到上线:需求文档的修改、确认和变更控制
5.1 文档状态怎么流转
需求管理平台里新增字段的需求文档一般会有草稿、评审中、已确认、开发中、待测试、已完成这几个状态。10001 这个单子目前是测试文档阶段,我理解为字段需求已经评审通过,进入验证环节。但这个“已确认”并不意味着所有细节都定了,接口联调时发现的字段参数问题,仍然要走变更记录,不能背地里改完不吭声。
我习惯在文档状态变更时同步更新一版“变更说明”,哪怕只是改了一个默认值,也要写清楚改前是什么、改后是什么、为什么改。这个动作看起来繁琐,但遇上两三个月后有人问“这个字段当初为什么这么设计”,翻文档比翻聊天记录靠谱得多。
5.2 多模块并发时如何避免互相影响
ADB 和 YUNTI 模块同在一个需求管理平台里,如果同期还有其他需求在动同一张表,字段新增就可能产生冲突。我这次处理时,先把两个模块涉及的数据库表、接口路径、页面路由都拉出来做了一份影响范围清单,并在文档里标注。如果后续有人要改同一张表,我会提醒对方先看我的字段定义,避免重复字段或者类型不一致。
另一个容易被忽略的是索引。新字段如果作为列表筛选条件,很可能需要加普通索引;但如果与其他需求并发,两个人同时加索引,可能造成表锁等待。所以数据库变更要排好顺序,尽量放在低峰期执行,并且提前把变更脚本发给 DBA 确认。
5.3 文档归档与知识沉淀
需求文档和测试文档最终要归档到系统里,不只是为了流程合规,更是为了以后做同类需求时有现成可参考的模板。我每次做完这类“新增字段”需求,都会把字段设计、回填方案、测试用例这套方法沉淀成一个通用模板。下次再有一个模块要加字段,直接复用,至少能省半天评审时间。
归档时不要只传一份终版文档,最好把需求澄清记录、评审会议纪要和变更记录三个附件一起挂上去。这样项目结束三个月后,谁来看都能还原当时的决策链路,不需要拉着当时的经办人重新讲一遍。
6. 一份可以直接抄作业的字段需求自检清单
6.1 需求文档内容自检
我给自己定了一个发布前的检查清单,每次都觉得检查完肯定没问题,结果一对照还能翻出来几个遗漏,整理成下面这版:
- 每个字段是否说明了中文名、英文名、类型、长度、必填性、默认值、字典项。
- 是否说明字段在哪些页面出现,列表、表单、详情、筛选、导出有没有遗漏。
- 是否说明新字段和现有旧字段的关系,有没有重复或可以复用。
- 是否说明历史数据回填方案,存量数据不满足新规则时如何兜底。
- 是否定义接口出入参和错误码,新增字段在异常情况下怎么返回。
- 是否画出权限矩阵,敏感字段有没有设置可见范围。
- 是否把需求条目和测试用例关联起来,评审时能逐条核对。
6.2 测试文档内容自检
测试文档这边我也有一个清单:
- 正常用例、边界用例、异常用例是否齐全。
- 是否覆盖前端、接口、数据库三层。
- 导出、排序、筛选、权限、历史数据这些跨功能链路是否都设计到了。
- 测试数据是否同时包含新数据和存量数据。
- 用例预期是否具体到可见的界面表现,而不是“系统正常”这类空话。
- 是否预留了回归执行人和执行时间,方便追踪测试进度。
6.3 上线前后的时间节奏参考
字段需求虽然小,节奏不能乱。我的建议是:需求澄清至少留半天,字段设计加历史数据方案留一天,评审会留一小时,研发开发一到两天,测试用例设计半天到一天,接口联调半天,全量回归一天。如果每个环节都压缩得很紧,最大的风险不是开发写不出代码,而是测试遗漏了边界场景,后面线上补数据可比开发的时候补麻烦得多。
最后再说一个自己的小习惯:每次上线前,我会把所有新字段的字典项、默认值、回填规则单独拉一个 Excel 给业务和测试各发一份,让大家在上线前哪怕不打开系统,也有一个统一的对表。这个动作成本极低,却能避免很多“我以为你改了,你以为我改了”的误会。需求管理和字段设计这件事,说到底不是替系统做决定,而是替团队把每个决定说清楚。