简介:面向系统工程与软件工程学习者及项目初期团队的需求分析模板,围绕新建或改造系统时如何明确目标、范围、定义与功能展开,适合课程设计、毕业设计及小型项目立项阶段参考。压缩包共1个doc文件,约26KB,篇幅精炼,可直接借鉴报告结构与表述方式。已有284人学习,说明其在需求分析入门与文档写作场景中具有一定参考价值。内容以高校工资管理系统为实例,覆盖编写目的、项目背景、功能定义、系统目标、测试环境与测试概要,并给出测试结果及用户管理、员工信息管理、工资标准设定、工资信息管理四大模块的划分思路;读者可据此理解需求收集、需求分类与优先级设定,掌握需求报告从背景分析到功能描述、再到测试验证的组织方法,为后续设计、编码与维护提供可复用的文档框架。
1. 需求分析模板不是填空纸:一份高校工资管理报告里藏着七条可验收条目
评审会上最常出现的一幕是:文档模板一拉,标题一填,功能列七八条,谁看一眼都说「挺全的」,然后开发照着做,等到财务第一次跑月度工资,发现「职称工资调整那天的差额没算进去」——翻回去看当初那条需求,只有五个字:工资调整管理。需求分析这件事的难点从来不是写不出文字,而是写出来的每一条别人能不能拿去验收。这份高校工资管理系统需求分析模板值得拆的地方也在这里:它把一个琐碎的工资业务压成了七条功能定义、四个功能模块、两级用户权限,后面还挂了测试概要和运行评价,形成了一条从「要做什么」到「怎么证明做对了」的链条。
它适合三类人:要交课程设计报告、需要一份结构完整的参照;第一次独立写需求文档、不清楚每段该写到什么颗粒度;以及做业务侧分析、需要一份能对着抄模块划分和权限划分的骨架。下面按结构、模块、字段口径、避坑、自检五层往下拆,每一层都落到能直接改写成自己项目文字的程度。
2. 拆开这份模板的骨架:三段结构各自挡住评审会的哪类追问
这份报告的骨架是清晰的三段:引言(编写目的、背景、功能定义、系统目标、测试环境)、测试概要、测试结果及发现(含功能结论、模块划分、运行评价)。很多人抄模板只抄了标题层级,没抄每段承担的「挡追问」职能,结果文档厚度够了,评审照样问穿。这一段就把每段的实际作用拆开。
2.1 编写目的与背景:把人工流程翻译成可计算的流程
原文的编写目的一句话就点到了要害——「把人工管理高校工资的流程,抽象为可在计算机上处理的自动模式」。这句是整份文档的锚点,后面所有功能都必须能回溯到「哪一步人工被替代了」。写法上有个很实用的公式:现状动作 → 痛点量化 → 转换动作 → 读者对象。现状动作是「每月手工填制大量表格」,痛点是「耗时长、易出错、核算工作量大」,转换动作是「数据入库、规则表驱动、按月生成」,读者对象是「开发小组 + 财务使用人员」。
背景段最容易写成抒情散文,原文也有一点这个倾向,但里面埋了几个能直接用的对比维度:检索速度、查找便利性、可靠性、存储量、保密性、成本。这六项其实就是非功能需求的雏形,写背景时顺手把它们记下来,后面第 4 章写非功能需求时直接搬过去,比临时编要靠谱得多。
| 段落 | 常见废写法 | 可验收写法 |
|---|---|---|
| 编写目的 | 为了完成系统开发 | 把月度工资核算从手工填表改为规则表驱动,替换掉 3 个手工环节 |
| 背景痛点 | 管理越来越复杂 | 教职工数量增长导致单月核算工时上升,人工核对易漏项 |
| 读者对象 | 供大家参考 | 开发组按此确定模块边界,财务按此确认字段口径 |
提示:编写目的里出现的每一个动词,后面都要有一个功能条目接住。写了「统计」却没有统计维度和输出形式,这条就是空的。
还有一个细节值得学:原文把「为使用者提供参考」也写进了编写目的。这在课程设计场景里很关键,因为需求文档往往同时是交付物和说明书,明确它的双重身份,后面写帮助文件、写使用说明才不会显得突兀。
2.2 功能定义:从一句话需求到七条能进测试用例的条目
原文列了七条:员工基本信息的录入修改删除、工资标准设定(职务工资、职称工资、其他工资)、工资信息浏览、员工工资表创建、工资调整管理、工资统计、用户级别设定与口令修改。这七条作为目录够用,作为需求不够——每条都缺操作者、前置条件、输入、输出、异常分支五个要素。
拿「工资调整管理」举例,这句在开发眼里是完全无法落地的。合格从业者的补法是把它拆成三个可判定的事实:调整对象是谁(单个教职工还是某个职称档次下的全部人)、调整生效时点是什么(当月生效还是次月生效)、调整后已结算月份怎么处理(重算还是保留原值)。这三个问题答不出来,这条需求就不算写完。
再拿「工资统计」举例,必须写清统计维度(按学院、按职称、按月份)、统计口径(应发、实发、扣款分项)、输出形式(屏幕表格、可导出文件、可打印报表)。原文只写了「工资统计」四个字,实际做的时候开发只能自己拍脑袋,拍错了就是返工。
改写时可以套一个固定句式,写起来快也不容易漏:「【角色】在【前置条件】下,对【对象】执行【操作】,系统输出【结果】;当【异常条件】时,系统【处理方式】。」这个句式看着啰嗦,但它逼着把异常分支写出来,而异常分支恰恰是测试用例的主要来源。原文的测试概要里只有「人员信息输入」「人员信息删除」两条,正是因为功能定义阶段没写异常,测试阶段自然也想不出该测什么。
2.3 系统目标与测试环境:Pentium Ⅲ 那一段今天该怎么改写
系统目标段的核心信息有四条:处理对象(教职工基本信息与工资信息)、工资分类方式(职务工资、职称工资、其他工资)、可执行动作(添加、修改、调整、查询、生成月表、打印)、质量诉求(简单、易用、小巧、经典、准确、高效)。这四条里前三条是硬需求,最后一条是形容词,形容词要么删掉,要么翻译成可测指标。
测试环境段写的是 Pentium Ⅲ 以上 CPU、128M 以上内存、Windows 98 以上系统、开发工具 Delphi 7.0。这套配置在今天当然跑不动任何东西,但这段的写法逻辑是对的:给出硬件下限、操作系统范围、开发工具、以及使用限制(不同管理级别有不同操作权限)。照着这个逻辑换成当代口径即可,比如双核以上、4G 内存、主流桌面系统、团队实际使用的语言与框架。
环境段的作用是「让别人能复现」,不是「展示配置」。所以真正该写清楚的是三件事:依赖的运行时或框架版本、数据存储方式(单机文件库还是网络数据库)、以及权限限制的生效位置(登录时校验还是每次操作时校验)。原文只写了「不同的管理级别有不同的操作权限」,没写校验发生在哪一层,这就是后面第 3 章权限矩阵要补的坑。
另外原文提到「可移植性:适用于各种操作系统」,这条放在今天依然常见,也依然是空话。可移植不是写在纸上的属性,是要付出代价的设计决策——数据库连接方式、文件路径分隔符、打印接口调用,每一处都可能把「可移植」打破。要么把它降级成「支持主流桌面系统」,要么在需求里明确不追求跨平台,二选一都比含糊着强。
2.4 测试概要与测试结果:只写「完全正确实现」等于没测
原文的测试概要要求用表格列出每项测试的标识符、测试内容,并说明实际测试工作与计划的差异及原因。这个要求本身很到位,可惜后面的测试结果只写了「功能测试 1 对人员信息输入功能进行测试,该功能完全正确实现」「功能测试 2 对人员信息删除等功能进行测试,该功能完全正确实现」。这种写法在评审里是过不了的,因为它没有留下任何可复查的痕迹。
一条能站住的测试记录至少要有五列:用例标识、输入数据、预期结果、实际结果、结论。输入数据要具体到值,比如「工号 E001,姓名张三,职称副教授,职务系主任」;预期结果要能比对,比如「列表中新增一行,工号唯一性校验通过,职称工资按副教授标准取 2800」;实际结果与预期不一致时,还要写差异原因和处理方式。
| 用例标识 | 测试内容 | 输入要点 | 预期结果 | 结论 |
|---|---|---|---|---|
| TC-EMP-01 | 员工信息录入 | 工号、姓名、学院、职称、职务全填 | 保存成功,列表可见 | 通过 |
| TC-EMP-02 | 工号重复录入 | 使用已存在工号 | 拒绝保存并提示工号重复 | 通过 |
| TC-EMP-03 | 员工信息删除 | 删除已有工资记录的员工 | 拒绝删除或提示先处理工资记录 | 待确认 |
| TC-STD-01 | 职称工资标准修改 | 修改副教授档金额 | 仅对生效日期之后月份生效 | 通过 |
注意 TC-EMP-03 那条「待确认」,这才是测试概要真正有价值的地方——它暴露了需求文档里没写清的一条规则:有历史工资记录的员工能不能直接删。这类问题在测试阶段发现是好结果,在结算日发现就是事故。测试概要不该是一张走过场的表,它应该是需求文档的第一轮压力测试。
模块划分和运行评价放在测试结果之后,逻辑上是「测完了,回头确认模块边界是否合理」。原文把系统分成用户管理、员工信息管理、工资标准设定、工资信息管理四块,这个划分在工资类系统里算相当标准的切法,下一章展开讲每块该怎么写细。
3. 把功能定义落成模块表:四模块划分与一张两级权限矩阵
模块划分是需求文档里最容易被低估的一节。写得好,后面数据库设计和接口设计基本照着走;写得糊,开发各写各的,最后拼不起来。原文的四模块切法——用户管理、员工信息管理、工资标准设定、工资信息管理——本质上遵循了「账号 → 主数据 → 规则 → 业务单据」的顺序,这个顺序值得单独说清楚,因为它决定了模块之间的依赖方向。
3.1 用户管理模块:两级权限不是写两个角色名就完事
原文的设定是:管理员是财务部门人员,可以对系统进行一切操作;教职员工是普通用户,只能运行个人工资查询和打印。这个两级划分在业务上没问题,但落到实现上还差好几层信息。
第一层是账号从哪来。是管理员手工添加,还是从人事系统同步?原文写的是「系统用户数据的添加、修改和删除」,也就是手工维护,那就必须补一条:员工信息删除时,对应的登录账号怎么处理——同删、禁用还是保留。这条不写,后面就会出现「人已经离职了账号还能登录查工资」这种问题。
第二层是口令策略。原文只写了「口令修改」,没写复杂度、有效期、失败次数限制。这些不是安全加分项,是需求文档该定的规则,因为不同规则对应的实现工作量差别很大。常见做法是:最少 8 位、含字母与数字、连续 5 次失败锁定 10 分钟、管理员可重置但不显示原口令。
第三层是越权行为。教职员工尝试访问他人工资记录时,系统是返回空列表、报错,还是跳回首页?这三种处理在测试用例里是完全不同的三条。原文没有涉及,但这是权限模块最该写死的一条。
第四层是权限校验的位置。是在登录时把角色写进会话、后续每次操作读会话,还是每次操作都回查一次权限表?前者性能好但角色变更不即时生效,后者即时但多一次查询。工资系统的角色变更频率极低,前者完全够用,但需求里要写明「角色变更后需重新登录生效」,否则运营侧会以为改完立刻生效。
3.2 员工信息管理与工资标准设定:主数据和规则必须分开
员工信息管理模块负责教职工基本信息的输入、修改、删除、查询,原文还提了一句「在高校管理中按照学院对信息进行管理」,这句话很关键——它说明「学院」是一个组织维度,不是一段自由文本。那就意味着需要一个学院字典表,员工表里存学院代码而不是学院名称,否则同一个学院出现三种写法,按月统计就废了。
工资标准设定模块负责职务工资标准、职称工资标准、其他工资标准的设定、修改、删除、保存。原文有一句很好的判断:「工资标准的依据恰好与教职员工的基本信息相一致,形成对应关系。」这句话点明了标准表与员工表之间是靠职称代码、职务代码关联的,而不是靠名称匹配。
这两个模块分开的意义在于变更频率不同。员工信息随时可能变(入职、离职、调岗),工资标准一般一年调一次。如果混在一个模块里,每次调标准都要碰员工数据,风险很高。分开之后,标准表可以独立做版本管理。
这里有个模板里没写、但实际项目一定会踩的点:工资标准需不需要历史版本。如果只存当前金额,那么去年 12 月已经结算的工资,今年 3 月再查,就会按新标准显示,财务一核对就发现对不上。正确做法是标准表带生效日期和失效日期,工资明细在核算时把当时用的标准金额快照下来。这一条不写进需求,后面基本要返工。
| 数据对象 | 变更频率 | 是否需历史版本 | 关联方式 |
|---|---|---|---|
| 员工基本信息 | 高 | 否(保留在职状态) | 按工号 |
| 职称/职务字典 | 低 | 否 | 按代码 |
| 工资标准 | 每年约一次 | 是,按生效区间 | 按类型+代码+日期 |
| 月度工资明细 | 每月一批 | 是,按月份隔离 | 按月份+工号 |
3.3 工资信息管理:按月生成工资表的时序约束要写死
工资信息管理是四个模块里最重的,原文列了六件事:工资表生成、个人工资查询、工资修改、工资结算、工资统计、工资表打印,并且说明「按月生成工资表,保存在数据库中」。这句话里藏着一个必须补上的设计:工资表是有状态的,不是一个可以随便改的二维表。
合理的状态序列是:草稿(已生成未确认)→ 已核算(金额算完,可复核)→ 已结算(金额锁定,不允许改明细)→ 已发放(归档,只读)。每个状态允许的操作不同,比如草稿允许重新生成,已核算允许人工调整单项,已结算只允许冲正不允许直接改,已发放只能查询和打印。这套状态机不写进需求,开发就会做成「任何时候都能改」,然后某天财务改了一个已发放月份的金额,账面直接对不上。
还有一条时序约束必须写:工资表生成依赖哪些数据。依赖项至少包括当月在职员工列表、当月的工资标准版本、当月的考勤或扣款数据(如果有)、上月的补发补扣项。这些依赖项没到齐就生成,结果一定是错的,而且是那种要人工逐条比对的错。
原文最后提到「帮助文件的制作,要求有较为完善的帮助文件」,这一点常被忽略。工资系统的使用者是财务人员,不是开发,操作说明的价值不亚于功能本身。需求里至少该写明帮助文件的覆盖范围:每个模块的操作步骤、常见错误提示的含义、以及月度结算的操作顺序。把操作顺序写清楚,比写十页界面说明都有用。
3.4 用一张权限矩阵把「谁能做什么」固定下来
两级角色 × 若干功能,最直观的表达就是矩阵。这张表放在需求文档里,后面既可以直接转成接口的权限注解,也可以直接转成测试用例的覆盖面。
| 功能点 | 管理员(财务) | 教职员工 | 未登录 |
|---|---|---|---|
| 员工信息新增/修改/删除 | 允许 | 禁止 | 禁止 |
| 工资标准设定与调整 | 允许 | 禁止 | 禁止 |
| 生成月度工资表 | 允许 | 禁止 | 禁止 |
| 工资结算与归档 | 允许 | 禁止 | 禁止 |
| 查询本人工资 | 允许 | 允许 | 禁止 |
| 查询他人工资 | 允许 | 禁止 | 禁止 |
| 打印本人工资条 | 允许 | 允许 | 禁止 |
| 打印全院工资汇总 | 允许 | 禁止 | 禁止 |
| 用户账号与口令管理 | 允许 | 仅改本人口令 | 禁止 |
矩阵画出来之后,往往会发现一些原文没覆盖的组合,比如「教职员工能否导出本人历史 12 个月工资」——原文只写了「查询和打印」,导出算不算打印?这类边界必须在需求阶段定性,否则实现阶段两个人会做出两种结果。
4. 数据字典与字段口径:三种工资项怎么拆才不会在结算日吵架
需求文档写到功能层,评审一般能过;写到字段层,才是真正决定这个系统能不能用的地方。原文把工资分成职务工资、职称工资、其他工资三类,这个分类看起来简单,但每一类的取值来源、精度、舍入规则、生效时点都必须定死,否则同一份工资表,财务算出来和系统算出来差两毛钱,就要查一整天。
4.1 三种工资项的口径定义
职务工资依赖职务代码,职称工资依赖职称代码,这两类都是「代码 → 标准金额」的直接映射,关键是要定义清楚一个员工同时有多个职务或多级职称时取哪一个。常见规则是取主职务、取最高职称,但这条规则必须写进需求,不能留给开发猜。
「其他工资」是三类里最危险的一项。它的名字就说明它是个兜底项,兜底项如果不定义边界,最后会变成什么都能往里塞的垃圾桶。合理的写法是把它再拆成若干有明确来源的明细项,比如工龄补贴、岗位津贴、补发、补扣,每项都有独立的计算规则和审批来源。
| 工资项 | 取值来源 | 计算方式 | 精度与舍入 | 生效时点 |
|---|---|---|---|---|
| 职务工资 | 职务代码 → 职务标准表 | 直接取值 | 两位小数,四舍五入 | 标准生效日所在月份 |
| 职称工资 | 职称代码 → 职称标准表 | 直接取值 | 两位小数,四舍五入 | 标准生效日所在月份 |
| 工龄补贴 | 入职日期 | 按整年数 × 单位标准 | 两位小数,向下取整到年 | 每年固定月份调整 |
| 补发/补扣 | 人工录入 + 审批单号 | 手工金额 | 两位小数 | 指定月份 |
| 应发合计 | 以上各项 | 求和 | 两位小数 | 随明细 |
精度这一栏看着琐碎,实际上是最容易出事的。三个人分别用浮点、用两位小数、用四位小数中间计算再舍入,最后合计能差出几分钱。需求里写一句「所有金额字段统一两位小数,中间计算保留四位,最终结果四舍五入到两位」,能省掉后面无数轮对账。
4.2 数据字典表的标准列
数据字典不是把字段名罗列一遍,每一列都要能回答一个问题。合格的字典表至少有八列:字段名、中文名、数据类型、长度、是否必填、取值范围或来源、约束说明、备注。前四列是给开发建表用的,第五到第七列是给测试设计用例用的,最后一列是给后来人看的。
| 字段名 | 中文名 | 类型 | 长度 | 必填 | 来源/取值 | 约束说明 |
|---|---|---|---|---|---|---|
| emp_id | 工号 | 字符 | 12 | 是 | 人事分配 | 全局唯一,不允许修改 |
| emp_name | 姓名 | 字符 | 30 | 是 | 人工录入 | 不允许全空格 |
| college_code | 所属学院 | 字符 | 8 | 是 | 学院字典 | 必须存在于字典表 |
| title_code | 职称代码 | 字符 | 6 | 是 | 职称字典 | 决定职称工资取值 |
| post_code | 职务代码 | 字符 | 6 | 否 | 职务字典 | 为空时职务工资计 0 |
| hire_date | 入职日期 | 日期 | — | 是 | 人工录入 | 不晚于当前日期 |
| emp_status | 在职状态 | 字符 | 1 | 是 | 枚举 | 0 在职 / 1 离职,离职不参与月度生成 |
| bank_acct | 工资卡号 | 字符 | 32 | 否 | 人工录入 | 存储时脱敏,展示时掩码 |
这张表里最值得注意的两列是「来源」和「约束说明」。来源决定了这个字段是人工填、字典选还是系统算;约束说明决定了测试能设计出多少条反向用例。原文的功能定义里写「员工基本信息的录入、修改、删除」,如果只到这一步,开发会做成八个自由输入框,然后工号重复、学院写成别名、入职日期填成未来日期,全都是运行时才暴露的问题。
4.3 用一段建表语句验证需求能不能落地
判断一份需求写得够不够细,有个很快的办法:拿着数据字典去写建表语句,写不下去的地方就是需求缺口。下面这段覆盖工资标准表和工资明细表,重点看两个约束——标准表的生效区间、明细表的标准快照。
-- 工资标准表:同一类型同一代码在同一生效日只能有一条记录 CREATE TABLE t_salary_std ( std_id BIGINT PRIMARY KEY, std_type CHAR(1) NOT NULL, -- 1 职务 2 职称 3 其他 std_code VARCHAR(8) NOT NULL, -- 对应职务/职称代码 std_name VARCHAR(64) NOT NULL, amount DECIMAL(10,2) NOT NULL CHECK (amount >= 0), effect_date DATE NOT NULL, -- 生效起始日,含当天 expire_date DATE NULL, -- 失效日,NULL 表示长期有效 CONSTRAINT uk_std UNIQUE (std_type, std_code, effect_date), CONSTRAINT ck_range CHECK (expire_date IS NULL OR expire_date > effect_date) ); -- 月度工资明细:按月份隔离,并锁定核算时使用的标准金额 CREATE TABLE t_pay_detail ( pay_month CHAR(6) NOT NULL, -- 形如 202405 emp_id VARCHAR(12) NOT NULL, item_code VARCHAR(8) NOT NULL, -- 工资项代码 amount DECIMAL(10,2) NOT NULL, std_snapshot DECIMAL(10,2) NULL, -- 核算时的标准金额快照 create_time TIMESTAMP NOT NULL, PRIMARY KEY (pay_month, emp_id, item_code) );第一张表的effect_date和expire_date组合,解决的是「标准调了以后历史工资会不会被改」这个问题。查询某月工资该用哪一版标准,条件就是effect_date <= 当月首日 AND (expire_date IS NULL OR expire_date > 当月首日)。这个条件在需求文档里应该以文字形式写清楚,而不是等到写 SQL 时才想。
第二张表的std_snapshot是保险栓。即使标准表被误改,明细里的金额也不会跟着变,因为核算那一刻的取值已经落库了。这个字段在需求阶段的表述方式是:「工资明细一经生成,其金额不随标准表变更而变化。」这一句话,值一个字段。
pay_month用六位字符而不是日期类型,是个小约定但很实用:月度工资是按「账期」而不是按「某一天」组织的,用字符型可以直接做前缀匹配和排序,也避免时区问题。
提示:能在需求阶段用一段 DDL 写出来的规则,就不要留到编码阶段用注释表达。写不出来的,八成是规则本身还没想清楚。
4.4 非功能需求:把「安全保密」翻译成可测的条款
原文的运行评价部分列了六项:硬件接口(标准打印机接口)、软件接口(通信接口,实现局域网信息共享)、故障处理(重装软件、检查网络)、安全保密性(设定权限、密码验证)、可移植性(适用各种操作系统)、可维护性(可简单维护)。这六项覆盖面对,但每一条都停在口号层。
非功能需求的写法是「指标 + 判定方式」。安全保密不能写「有密码验证」,要写「口令最少 8 位且含字母与数字,连续 5 次失败锁定 10 分钟;教职员工访问非本人工资记录时返回无权限提示,并记录操作日志」。可维护性不能写「可简单维护」,要写「工资标准调整无需修改代码,通过标准维护界面完成,调整后新生成月份自动生效」。
| 原始表述 | 问题 | 可测表述 |
|---|---|---|
| 有安全保密 | 无法判定 | 口令策略 + 失败锁定 + 越权日志三件套,逐条可验 |
| 适用于各种操作系统 | 无法判定 | 明确支持的系统范围,其他系统不承诺 |
| 可简单维护 | 无法判定 | 标准调整走界面、字典扩展不改代码、日志可按月清理 |
| 故障处理:重装软件 | 未定义数据 | 重装不影响已有数据,数据目录与程序目录分离 |
| 标准打印机接口 | 未定义输出 | 工资条与汇总表均支持预览后打印,A4 纵向 |
故障处理那一条其实藏着一个很实际的要求:程序目录和数据目录要分开。很多单机版系统把数据库文件放在安装目录下,用户一重装,数据全没了。需求里写一句「数据文件存放于独立目录,卸载或重装程序不删除该目录」,就是给运维留的后悔药。
5. 避坑:照抄这份模板最容易翻车的五个地方
模板类资源最大的风险不是写得不够,而是抄得太顺。下面五条都是照着这种结构写文档时真实会遇到的坑,每条按现象、原因、解决三段落。
5.1 坑一:把「工资调整管理」当成一条需求写完就过
现象是文档评审一路绿灯,开发阶段开始扯皮——有人说调整是改标准,有人说调整是改个人金额,两个人各做一半,最后合并时接口对不上。
原因是这类动词性需求没有宾语和时点。调整的对象、调整的生效范围、调整后历史数据怎么处理,三个都没定。需求文档里出现「XX 管理」「XX 处理」这种词,基本可以判定是空的。
解决办法是给每条动词性需求强制补三个字段:作用对象(单条记录还是批量)、生效时点(当月、次月、指定月)、历史处理(重算、保留、冲正)。这三栏填完,一条模糊需求会自然分裂成三条清晰需求。我一般的做法是在功能定义表里直接加这三列,填不出来就先挂着,不许进评审。
5.2 坑二:工资标准只存当前值,历史月份对不上账
现象是系统上线三个月后,财务查去年 12 月的工资明细,发现职称工资的金额和当时发的不一致,一查是今年调了标准,把老数据也带变了。
原因是标准表没有版本概念,只有一个金额字段,改了就是覆盖。而工资是有历史属性的数据,任何影响金额的规则都必须可回溯。
解决办法是在标准表引入生效区间,并在明细表保存核算时的金额快照。这两步做完,历史数据就锁死了。代价是标准维护界面要支持「新增一版」而不是「编辑当前」,交互上多一步,但对账的时候能救命。这套思路不只适用于工资,任何「规则 + 单据」结构的系统都该这么设计。
5.3 坑三:权限只写角色名,不写越权时的行为
现象是测试阶段发现普通用户直接拼接口地址能拿到别人的工资记录,开发说需求里只写了「只能查询个人工资」,没说被拦住之后返回什么,于是就没做拦截。
原因在于权限需求只描述了正向路径,没描述反向路径。正向路径是「允许做什么」,反向路径是「不允许时系统表现成什么样」,后者才是测试用例的来源。
解决办法是把权限矩阵补上「未授权时的系统行为」一列,统一约定为:拒绝操作、给出明确提示、记录一条操作日志。三条缺一不可,尤其是日志,出问题时它是唯一的黑匣子。另外,校验位置也要写明——在服务端入口统一校验,还是每个功能各自校验,前者不容易漏。
5.4 坑四:测试环境照抄旧配置,别人根本复现不了
现象是把文档发给同事,对方按环境段落装了一遍,跑不起来,来回问了三轮才发现缺一个数据库驱动,而文档里只写了操作系统版本。
原因是环境段只写了硬件和系统,没写运行时依赖。Pentium Ⅲ、128M、Windows 98 这套参数在当年是完整的,因为 Delphi 程序编译出来就是单个可执行文件,依赖很少;换成现在的技术栈,依赖项多了不止一个数量级。
解决办法是把环境段拆成四块:硬件下限、操作系统范围、运行时与依赖清单(含版本)、数据存储方式与初始化步骤。最后一块最关键——空库怎么建、初始管理员账号怎么来、字典数据怎么导入,这三步不写,别人拿到代码也跑不出一个能用的系统。
5.5 坑五:测试结果写成「完全正确实现」,等于给自己埋雷
现象是测试章节只有两行字,每行都是「该功能完全正确实现」。交付后第一个月,财务录入一个工号重复的员工,系统直接覆盖了原记录,追责时翻文档,发现没有任何一条用例覆盖过这个场景。
原因是把测试当成了形式,只记录通过项,不记录用例设计和边界值。原文的测试概要其实要求了「指明实际测试工作与计划的差异及原因」,这个要求本身是对的,只是执行时被简化掉了。
解决办法是每个功能至少配三条用例:正常路径、边界值、异常路径。员工录入就是正常录入、工号重复、必填项为空;工资生成就是正常月份、跨月补发、无在职员工。用例写不出来,说明功能定义没写清,回头补上再测。血泪经验是:测试用例的覆盖率,基本等于需求文档的完整度,两者是同一件事的两个视角。
6. 从模板到评审通过:追溯矩阵与一份可打印的自检清单
模板用得对不对,最后有个很硬的检验方式:能不能把每一条功能需求,沿着「模块 → 数据字段 → 测试用例」一路串起来。串得通,说明文档自洽;串到某一环断了,断点就是评审时会被问到的地方。我习惯在文档最后加一张追溯矩阵,四列就够,不占篇幅但极其实用。
| 需求编号 | 功能点 | 所属模块 | 关键数据 | 对应用例 |
|---|---|---|---|---|
| R-01 | 员工信息录入 | 员工信息管理 | emp_id、college_code | TC-EMP-01/02 |
| R-02 | 员工信息删除 | 员工信息管理 | emp_id、emp_status | TC-EMP-03 |
| R-03 | 职称工资标准设定 | 工资标准设定 | std_type=2、effect_date | TC-STD-01 |
| R-04 | 月度工资表生成 | 工资信息管理 | pay_month、std_snapshot | TC-PAY-01/02 |
| R-05 | 个人工资查询 | 工资信息管理 | emp_id、pay_month | TC-QRY-01 |
| R-06 | 口令修改 | 用户管理 | 账号、口令策略 | TC-USR-01 |
矩阵填完之后做一遍反向检查:哪条需求找不到用例,说明测试没设计;哪条用例找不到需求,说明有功能是凭空加的,要么补需求要么删功能。这一遍走下来通常能砍掉两三成的水分。
再给一份可以打印出来贴在显示器边上的自检清单,按顺序过:
- 编写目的里出现的每个动词,在功能定义里都有对应条目。
- 每条功能需求都写清了角色、前置条件、输入、输出、异常分支五项。
- 所有「XX 管理」类条目都已拆成具体动作,没有遗留动词性空需求。
- 工资标准类数据都有生效区间,工资明细类数据都有金额快照。
- 权限矩阵包含未授权行为与日志记录,且写明校验发生在哪一层。
- 数据字典每个字段都填了来源与约束,没有「类型待定」。
- 测试概要的每条用例都有具体输入值和预期结果,没有「完全正确实现」。
- 环境段包含依赖清单与空库初始化步骤,别人照着能跑起来。
这份清单过不完,文档就别发出去评审——省下的那一小时,会在开发阶段以三倍时间还回来。
从那以后我每写一份需求文档,都会先把功能定义那一段单独打印出来,逐条往追溯矩阵里填,凡是填不出用例编号的条目,一律退回重写,不管它看起来多合理。需求文档的价值从来不在篇幅,而在于每一条都能被人拿去验证。希望帮到你。
本文还有配套的精品资源,点击获取