
见过太多人把功能测试理解成把页面挨个点一遍没报错就算通过然后交付前一周才开始慌。真到了线上用户点了一个谁都没想过的组合操作数据串了、状态错乱、金额算错回头一查功能测试的用例里压根没有这一条。问题不在于测试人员不勤快而在于大多数人做的是界面操作复现而不是功能逻辑验证。这篇内容我想把功能测试从需求拿到手、到用例设计、到执行定位缺陷、再到回归收尾的完整链路拆开讲一遍包含我这些年踩过的坑和总结出来的判断标准。刚入行的测试同学可以当成一份完整的工作流程参照做了几年但一直觉得测试做得有点虚的同学也可以对照看看是哪一环漏了。1. 功能测试到底在测什么从点一遍到验证需求闭环的认知差功能测试的定义谁都背得出来验证软件的各项功能是否符合需求规格。但定义和实际操作之间隔着一条巨大的鸿沟。我在带新人的时候经常问一个问题你现在测的登录功能包含哪些内容十个人里有八个回答输入正确的账号密码能登录进去就行了。这个回答没错但它只覆盖了登录这个功能不到三分之一的内容。1.1 一句功能没问题背后其实藏着五个问题层次我把功能测试要覆盖的内容拆成五个层次从下往上看越往上越容易被忽略第一个层次是正常路径也就是最标准的操作流程能跑通。输入合法数据、按标准步骤操作、得到预期的结果。这是所有人都能想到的层面也是最有安全感的一层因为它最容易验证。第二个层次是异常路径输入非法数据、执行非法操作、跳过前置步骤、重复提交、中途取消。这一层的价值极高因为线上问题绝大多数出在这里。账号输入不存在的用户名会怎样密码输错五次会锁定吗提交按钮连点三次会不会生成三笔订单第三个层次是边界与极值这里的边界不只是数值大小还包括长度极限、数量极限、时间边界、状态临界。备注字段最多 200 字那 200 字、201 字、0 字、全是空格、包含特殊符号分别怎么处理列表最多显示 20 条那第 21 条会被截断还是分页第四个层次是状态流转同一个按钮在不同状态下应该有不同表现。订单只有待支付时能取消已发货时取消按钮应该消失或置灰。很多缺陷就来源于状态判断没做全页面上按钮还在点下去接口直接报错。第五个层次是业务闭环也就是单个功能点串起来之后整条链路是否自洽。下单、支付、发货、收货、评价、退款这条链路上任何一环的数据没有正确流转到下一环都会导致后面全部出错。把这五层拆开之后你会发现一个登录功能真正要测的至少包括正确凭证、错误密码、不存在的账号、空输入、超长输入、大小写敏感、前后空格、验证码错误与过期、连续失败后的锁定策略、记住密码、多端登录互踢、密码找回、会话过期跳转以及登录成功后跳转目标页面的参数是否正确带上。这就是点一遍和验证需求闭环之间的差距。1.2 功能测试与冒烟、系统、验收测试的边界很多人把这几类测试混着说导致工作安排上出现重复劳动或者漏测。我用一张表把它们区分清楚测试类型核心目的覆盖范围执行时机典型执行者冒烟测试确认主流程可测只覆盖最核心的几条主干版本提测后第一时间测试人员功能测试验证功能逻辑与需求一致按用例全量覆盖功能点冒烟通过后测试人员系统测试验证整体系统在真实环境下的表现功能性能兼容安全功能测试基本稳定后测试团队验收测试确认满足业务方使用要求以业务场景为主交付前业务方/产品这里有一个很实际的经验冒烟测试不通过不要硬着头皮往下测。我见过不少团队提测版本主流程都跑不通测试人员还是坚持把用例执行完最后提了八十个缺陷开发改完发现全是同一个根因引起的连锁反应前面测的全是无效工作。正确的做法是冒烟挂掉就立刻打回让开发修完主流程再重新提测这样能省下大量重复执行的成本。另外补充一点功能测试和系统测试不是先后关系那么绝对。比如兼容性功能验证——同一个功能在不同浏览器下表现是否一致——它既属于功能验证也属于兼容性测试的一部分。实际工作中不用太纠结归类关键是别漏。1.3 判断功能测试做没做透的三个信号怎么知道自己这轮功能测试是不是做完了我给三个可观察的信号。信号一你能画出这个模块的状态流转图并且每一对状态转换都有对应的用例。如果你画不出来说明你对业务的理解还停留在界面层面。信号二你能说出每一个输入框的数据规则包括类型、长度、格式、是否必填、是否唯一、是否需要脱敏。说不出来说明边界测试一定漏了。信号三别人问如果用户在 A 步骤做了 X 操作会怎样你不需要重新打开系统去看就能回答。这说明你已经建立了完整的业务模型而不是靠临场发挥。这三个信号本质上指向同一件事功能测试的深度取决于你对业务的理解深度而不是你点鼠标的速度。2. 拿到需求文档之后功能测试的输入物料与拆解路径需求文档是功能测试的起点但它几乎从来不是完整的。我职业生涯里遇到过的完美需求文档一只手数得过来绝大多数文档都存在模糊、缺失、前后矛盾的问题。所以拿到需求之后的第一件事不是写用例而是把不确定的地方全部找出来。2.1 需求文档里读不出来的东西靠什么补需求文档通常只写是什么不写为什么和边界在哪。比如文档上写着用户可以修改昵称这句话至少藏着十个问题修改次数有限制吗昵称长度范围是多少允许特殊字符和表情符号吗是否需要唯一修改后多久生效历史评论里的旧昵称会一起变吗其他用户看到的是新昵称还是旧昵称修改需要审核吗审核期间显示什么被举报过的昵称还能改吗这些问题的答案有三种获取途径优先级从高到低一是直接问产品。别怕问问问题比事后返工便宜得多。但问也要讲方法不要问这个功能怎么测而要问如果用户做了 X期望的结果是什么。前者让人无从答起后者能直接得到可验证的结论。二是翻历史版本和相似功能。同一个系统里通常存在类似的实现参照已有功能的处理方式往往就是最合理的答案。比如另一个模块的备注字段限制 500 字那这个新增的备注字段大概率也是同一套规则。三是参照行业通用做法。比如密码强度规则、手机号格式校验、金额保留两位小数这些都有相对统一的行业惯例。按惯例设计用例如果产品有不同意见他会主动纠正你这本身就是一次有效沟通。我习惯在需求评审之后整理一份待确认问题清单逐条记录问题、我的假设、以及最终确认的结论。这份清单有两个作用一是避免口头确认后被遗忘二是将来真的出了争议它有据可查。2.2 把需求拆成功能点清单的具体做法从需求到用例之间必须有一步拆解否则很容易出现文档看完了但还是不知道从哪下手的状态。我的做法是先把需求拆成功能点清单格式大致是这样模块用户中心 功能点昵称修改 子功能1入口展示按钮可见性、置灰条件 子功能2弹窗/页面打开与关闭 子功能3输入校验长度、字符类型、敏感词 子功能4唯一性校验 子功能5提交与保存 子功能6修改后的展示本端、他端、历史数据 子功能7修改次数限制 子功能8异常处理网络中断、重复提交、超时这个清单的价值在于它把一句模糊的需求变成了可以被逐条覆盖的检查项。写用例的时候对着这个清单往下走基本不会出现大面积漏测。拆解的时候有个技巧沿着数据的生命周期走。数据从哪来输入→ 怎么存处理→ 存到哪存储→ 从哪读查询→ 怎么展示输出→ 什么时候消失删除/归档。这条链路走一遍功能点基本就全了。2.3 隐性需求的挖掘从界面元素反推业务规则有一类需求文档里根本不写但必须测——隐性需求。它们通常表现为一些理所当然应该这样的行为。比如一个查询列表页面界面上有搜索框、时间筛选、分页器、导出按钮。文档里可能只写了支持按条件查询。但实际要测的包括搜索关键词前后的空格是否被自动去除、搜索结果是否高亮、无结果时的空状态展示、切换筛选条件后页码是否重置为第一页、导出的是当前页数据还是全部数据、导出的数据是否和列表一致、导出数据量过大时会不会超时。再比如一个表单页面界面上有必填项标记、有字符计数器、有提交按钮。隐性需求包括必填项为空时提交按钮是否可点、错误提示出现在什么位置、多个字段同时报错时是否都显示、输入过程中错误提示是否实时消失。挖掘隐性需求最有效的方法是换位思考如果我是用户我会怎么用这个功能如果我是想搞破坏的人我会怎么绕过限制这两个视角能覆盖掉大部分隐性需求。3. 用例设计方法的组合拳等价类、边界值、判定表、场景法怎么配合用用例设计方法大家都背过但真正的问题在于什么时候用哪个。单一方法用到底必然出问题只用等价类会漏边界只用场景法会漏组合只用错误推测会漏系统性。我总结出一套组合使用的顺序下面逐个说。3.1 等价类与边界值不是背概念是要算边界等价类划分的核心是把输入域分成若干个子集每个子集里取一个代表值。听起来简单实际操作中最容易出错的地方是划分依据。举个例子一个年龄输入框要求 18 到 60 岁。有效等价类只有一个18 到 60 之间的整数。无效等价类至少有小于 18 的整数、大于 60 的整数、非数字字符、空值、小数、负数、超长数字、包含空格、包含正负号、全角数字。很多人只划了前两个无效等价类就开始写用例了后面那一串全漏掉。等价类划完之后边界值必须单独补一轮而且不只是取边界本身。以 18 到 60 为例需要覆盖的值包括17、18、19、59、60、61如果输入是浮点数还要考虑 17.9、18.0、18.1。如果边界是按字符长度算的还要考虑边界值的字符组合——比如限制 10 位那第 10 位是中文字符还是英文字符占用的存储长度是不一样的。这里有个特别容易被忽略的点边界的定义依赖数据类型。一个字段限制最多 10 个字符在 Java 后端可能按 UTF-16 code unit 算在数据库里可能按字节算在中文字符占 3 字节的情况下10 个汉字在后端是 10 个字符在数据库可能是 30 字节。如果两边规则不一致就会出现前端提示没超限后端插入报错的经典问题。3.2 判定表与因果图多条件组合时怎么收敛用例数当一个功能的输出结果由多个输入条件共同决定时等价类和边界值就不够用了这时候上判定表。举个电商场景优惠券能否使用取决于四个条件——订单金额是否满门槛、商品是否在适用品类内、优惠券是否在有效期内、该用户是否已用过这张券。四个条件每个两个取值理论组合是 16 种。用判定表列出来是这样的序号满门槛品类匹配在有效期内未使用过结果1是是是是可用2否是是是不可用3是否是是不可用4是是否是不可用5是是是否不可用6否否否否不可用关键技巧是不需要穷举所有组合只需要覆盖每个条件单独不满足和全部满足这几种情况。上面四个条件理论上最少只需要 5 条用例就能覆盖所有条件的独立影响。如果条件数量特别多可以用正交实验法进一步压缩代价是放弃一部分组合覆盖。判定表的隐藏价值在于它能帮你发现需求本身没定义清楚的组合。比如订单金额不满门槛但同时品类不匹配应该提示哪个错误这个问题产品可能从来没想过但用例写到这里就必须问。3.3 场景法与状态迁移把业务流转画成一张可遍历的图场景法适合业务流程型功能核心是基本流 备选流。基本流就是最顺利的那条路径备选流是各种岔路。以用户下单为例基本流是选商品 → 加购物车 → 填地址 → 选支付方式 → 提交订单 → 支付成功。备选流包括购物车商品失效、地址超区、余额不足、支付超时、支付中途返回、重复提交、库存不足、限购数量超出。场景法的操作方法是先把基本流画成一条线然后在这条线的每一个节点上问这里可能出什么岔子把岔子画成分支。分支画完之后从起点到终点每一条完整路径就是一条用例。状态迁移法和场景法互补。它关注的是对象在什么状态下可以做什么操作。比如一个订单对象有待支付、已支付、待发货、已发货、已完成、已取消、退款中、已退款。每个状态能触发哪些操作、会迁移到哪个状态画成一张表当前状态允许操作迁移后状态待支付支付已支付待支付取消已取消待支付超时未支付已取消已支付申请退款退款中已支付发货待收货待收货确认收货已完成退款中退款成功已退款画出这张表之后用例就很清楚了每一个允许操作都是一条正向用例每一个不允许的操作都要验证是否被正确拦截。不允许的操作往往是最容易出问题的地方因为开发写代码时只考虑了正向流程很少主动加状态校验。3.4 错误推测法经验怎么变成可复用的清单错误推测法听起来最玄其实它是最能体现经验价值的方法。它的本质是基于对系统实现方式的了解推测哪里最可能出错。常见的高危区域有这么几类边界附近的浮点数运算、并发场景下的库存扣减、时间相关的逻辑跨天、跨月、闰年、夏令时、字符串处理空字符串、null、空格、emoji、转义字符、字符集问题中英文混排、生僻字、分页与排序相同排序值的稳定性、缓存与数据库不一致、异步任务的执行顺序。我把这些东西整理成了一份个人清单每次做功能测试时拿出来过一遍效率比临时想高得多。举几个具体的例子金额计算用 0.1 0.2 会不会出现精度问题用浮点数存储金额的系统在多次累加后可能出现 0.30000000000000004 这种结果。时间边界23:59:59 提交的订单归属哪一天跨月、跨年的统计报表对不对分页稳定性如果排序字段有大量重复值翻页时会不会出现某条数据重复出现或消失文本处理粘贴一段带换行符和制表符的内容会不会破坏页面布局或者存进数据库时被截断并发操作两个用户同时抢最后一件库存商品会不会都下单成功这份清单的每一条都是我在真实项目里遇到过或者见过别人遇到的问题它比任何教科书都实用。4. 用例评审与数据准备动手之前最容易被跳过的一环写完用例直接开测是效率最高的做法也是最容易翻车的做法。我用过很长一段时间这种方式直到有一次上线后暴露出一个所有测试人员都没考虑到的场景才意识到用例评审的价值。4.1 用例评审要评什么别开成朗读会我参加过很多次把评审开成朗读会的用例评审写用例的人从头念到尾其他人低头看手机念完散会。这种评审除了浪费时间没有任何作用。有效的用例评审应该聚焦三件事第一是覆盖完整性。把功能点清单和用例做一次映射看有没有功能点没有对应用例。这一步可以提前让评审者准备而不是现场想。我通常会用一张简单的对照表左边是功能点右边是关联的用例编号缺了哪个一眼就能看出来。第二是用例本身的可执行性。随机抽几条用例让没写过的人读一遍看能不能直接照着执行。如果一条用例需要读的人反复追问这里到底要点哪个按钮说明前置条件写得不够清楚。第三是预期结果的准确性。这是最容易出问题的地方。很多用例的预期结果写的是操作成功这不是预期结果这是敷衍。预期结果必须是可观察、可判断的具体描述比如页面跳转到订单详情页订单状态显示为待支付订单金额显示为 199.00。评审还有一个隐性收益开发人员如果参与评审往往会主动说出很多实现细节比如这个字段其实是异步更新的页面刷新后才会变这个接口有缓存5 分钟内返回的都是旧数据。这些信息对设计用例极有价值比文档靠谱得多。4.2 测试数据准备的四种手段及适用场景测试数据准备是功能测试里最耗时的环节之一很多人会把大量时间花在造数据上。我把常用手段列一下各有适用场景手动界面造数直接通过系统界面一步步操作生成数据。优点是数据最真实、状态最完整缺点是慢而且有些状态比如已过期根本造不出来。适合少量、结构简单的数据。数据库直接写入直接用 SQL 往表里插数据。速度快能造出任意状态的数据。但风险很高——如果表之间有外键约束、有触发器、有依赖其他表的冗余字段直接插入很容易造出脏数据导致测试结果不可信。用这招之前一定要弄清楚表结构和数据之间的依赖关系。调用接口造数用脚本或工具批量调用业务接口生成数据。这是最推荐的方式因为走的是和真实业务一样的链路生成的数据一定是合法的。缺点是脚本需要维护接口变更时脚本也要跟着改。数据快照与还原在测试开始前把数据库做一次快照测试过程中随便折腾测完恢复快照。适合需要反复测试同一场景的情况。但要注意如果测试环境和别人共用快照恢复会影响其他人的工作。实践中通常是组合使用主干数据用接口造边界数据用 SQL 补回归测试前做快照。4.3 用例的维护成本与复用设计写用例容易维护用例难。一个项目做半年用例库就会变得臃肿不堪大量用例因为需求变更而失效但没人敢删。我后来总结了几条降低维护成本的做法按功能点组织不按执行顺序组织。用例的编号和分组应该跟功能结构一致而不是跟某一次测试的执行顺序一致。需求变更时只需要改动对应功能点下的用例。把公共前置条件抽出来。如果 20 条用例都需要已登录且有权限的账号就把它抽成一条公共前置说明而不是在每条用例里重复写 20 遍。这样账号规则变了只需要改一处。给用例标注优先级和类型。优先级用来决定回归测试时执行哪些类型正向/异常/边界/性能用来做覆盖度分析。没有这两个维度用例库就是一团乱麻。定期清理但要留痕。失效的用例可以标记为废弃而不是直接删除万一日后需要追溯历史行为还能查得到。5. 执行阶段缺陷定位、复现、描述与跟踪的完整链路用例执行看起来是机械劳动实际上这是最能拉开测试人员水平差距的环节。同样发现一个异常有的人提一个模糊的缺陷单开发来回问三轮有的人直接给出根因线索开发十分钟改完。5.1 发现异常后的十分钟先判断是缺陷还是环境问题发现异常的第一反应不该是提缺陷而是判断这是不是真缺陷。我见过太多假缺陷浪费双方时间常见的假缺陷来源包括环境问题测试环境的数据和配置跟预期不一致比如某个开关没打开、缓存没清、依赖的第三方服务在维护。数据问题测试数据本身被改脏了比如上一条用例修改了共享数据导致这一条用例的前置条件不成立。用例问题用例的预期结果写错了或者步骤遗漏了某个必要操作。浏览器缓存前端资源更新了但浏览器还在用旧缓存表现就是代码明明改了但还是老样子。判断方法很朴素换一个干净的环境或账号重新执行一遍。如果复现了再看是不是数据问题——换个账号或者重置数据再试。两次都能稳定复现基本可以判定是缺陷。这里有个经验先看日志再下结论。后端日志、接口返回、浏览器控制台的报错信息往往能直接指出问题在哪一层。我习惯在提交缺陷之前先抓一下接口请求和响应把关键的报错信息附在缺陷单里。这一步多花两分钟能省下开发半小时的排查时间。5.2 缺陷描述模板与一个反例缺陷描述的核心原则是让没参与测试的人照着描述能独立复现。一个完整的缺陷描述包含标题、环境信息、前置条件、复现步骤、实际结果、预期结果、复现概率、附件截图、录屏、日志、接口报文。先看一个反例标题登录有问题 描述登录的时候报错了麻烦看下。这个缺陷单的问题在于什么环境什么账号怎么操作才报错报的什么错必现还是偶现开发拿到这个单子只能来问你一来一回至少半小时。再看一个合格的写法标题【用户中心】使用已锁定的账号登录时页面提示系统异常而不是账号已锁定 环境测试环境Chrome 120账号 test_locked_01 前置条件账号 test_locked_01 已连续输错密码 5 次处于锁定状态 复现步骤打开登录页输入账号 test_locked_01输入任意密码点击登录 实际结果页面弹出系统异常请稍后重试接口返回 500 预期结果页面提示账号已锁定请 30 分钟后再试接口返回业务错误码 40001 复现概率100% 附件录屏.mp4、接口响应报文.txt这两份缺陷单的差距本质上是我发现了问题和我帮你定位了问题的差距。5.3 严重程度与优先级的区分严重程度Severity和优先级Priority是两个独立维度很多团队把它们混为一谈导致排期混乱。严重程度衡量的是缺陷对系统的影响崩溃、数据丢失、主流程阻断属于致命功能不可用属于严重功能部分异常属于一般界面文案、样式问题属于轻微。优先级衡量的是修复的紧急程度它由业务价值决定而不是技术影响。两者的组合关系可以用一张表说清楚情况严重程度优先级举例影响主流程且必现致命高支付接口返回 500所有人无法下单影响主流程但概率低严重高百万分之一概率的金额计算错误不影响主流程但影响面广一般高首页错别字所有用户可见技术影响大但业务价值低严重中某个废弃功能的接口报错影响小且场景罕见轻微低极端分辨率下的布局错位有一类缺陷要特别处理偶现的严重缺陷。它的严重程度很高但复现概率低开发往往不愿花时间排查。这种时候我会尽量去收集现场信息——发生时的日志、用户操作路径、并发情况——把复现条件缩小到可控范围再提交。光说偶尔会出错基本不会有人理你。6. 回归、冒烟与探索式测试怎么分工一轮功能测试执行完提了一堆缺陷开发改完之后要回归。回归是功能测试里最容易被做敷衍的环节——要么全量重跑一遍耗时太长要么只验证改动的点导致漏测。6.1 回归范围怎么圈影响面分析回归范围的核心是影响面分析也就是判断这次代码改动可能波及哪些功能。分析方法分三步走第一步是看代码改动范围。让开发说明改了哪些文件、哪些方法。如果改动的是公共组件、工具类、基础服务那影响面就很大如果只是某个页面里的一行文案影响面就很小。第二步是看依赖关系。调用关系、数据依赖、配置依赖都要考虑。比如一个公共的金额计算工具类被修改了所有涉及金额的功能都要回归哪怕那些功能这次一行代码都没动。第三步是按优先级确定回归集合。常用做法是三级回归回归级别覆盖范围适用场景耗时占比冒烟回归核心主流程每次提测10%影响面回归改动点 关联功能每轮缺陷修复后40%全量回归所有功能上线前100%实际工作中很多团队会把全量回归交给自动化把人工测试集中在影响面回归上。这是一个合理的分工但前提是自动化的覆盖率足够高而且用例本身是可靠的。6.2 探索式测试的会话式管理探索式测试经常被误解成随便点点。它有方法只是不预先写用例。我常用的做法是会话式管理设定一个固定时长比如 90 分钟明确一个测试目标比如验证订单退款流程的异常处理然后在这个目标范围内自由探索过程中记录发现的问题和走过的路径。探索式测试最有效的几个切入点数据流追踪跟着一条数据走完整条链路看它在每个环节的状态是否正确。异常注入主动制造异常条件比如断网、重复提交、超长输入、特殊字符。边界穿越在功能的边界上来回切换比如反复切换状态、反复进出页面。权限交叉用不同角色的账号访问同一个功能看权限控制是否严密。有一个非常实用的技巧把探索过程录屏。因为探索式测试的路径是临时的一旦发现问题光靠回忆很难准确复现。录屏能帮你回溯到出问题的那一步。6.3 自动化在功能测试里的合理位置自动化不是功能测试的替代品它是功能测试的放大器。它的合理位置有三个一是回归测试。稳定的、重复执行的正向用例最适合自动化尤其是冒烟级别的核心流程。二是数据准备与校验。批量造数、批量校验数据正确性这类工作人工做极其枯燥且容易出错。三是接口层面的功能验证。界面测试跑得慢、不稳定把大量功能逻辑验证下沉到接口层效率会高很多。不适合自动化的部分也需要说清楚界面布局、交互体验、探索式测试、一次性验证的异常场景这些交给人工更划算。我见过强行把一切自动化的团队最后维护脚本的成本比手工测试还高。7. 功能测试里最典型的坑前面讲的都是应该怎么做这一节想说说容易做错什么。这些都是我在实际项目里反复遇到的问题。7.1 需求歧义导致的返工有个很典型的案例需求文档写着用户连续输错密码 5 次后锁定账号。测试用例写的是输错 5 次后第 6 次登录失败。开发实现的是输错 5 次第 5 次直接锁定。看起来只差一次但上线后客服收到大量投诉——用户觉得自己明明只输错了四次就被锁了。这类问题的根源在于需求描述里的模糊词连续锁定失效及时大量。这些词在不同人眼里含义不一样。应对方法是在需求评审时把模糊词逐个量化。连续是指不间断的连续还是累计中间成功登录一次会不会重置计数锁定是锁定多久锁定期间的提示文案是什么锁定状态能否被管理员解除我现在养成了一个习惯读需求时把所有形容词和程度副词圈出来逐个确认。这个习惯帮我避免了很多次返工。7.2 数据污染与用例相互干扰测试数据被污染是导致假缺陷和用例不可重复执行的主要原因。典型场景用例 A 创建了一条订单用例 B 需要验证订单列表的总数。如果用例 A 的数据没清理用例 B 的预期结果就永远不对。更麻烦的是这种问题不会立刻暴露可能今天跑是对的明天跑就不对了。解决思路有三条一是每条用例自带数据清理步骤测完把自己造的数据删掉二是用独立的数据空间比如每个测试账号的数据互不干扰三是执行前重置数据快照。第三条最彻底但需要测试环境支持快照恢复。如果做不到至少要做到用例之间有明确的数据依赖声明让执行的人知道哪些用例必须按顺序跑。7.3 只测正向路径的惯性这个坑前面提过但值得再展开说。只测正向路径的惯性来源很实际正向路径能跑出结果有成就感异常路径往往需要构造复杂条件还可能被开发说这个场景用户不会这么操作。但线上问题几乎全部来自异常路径。用户的真实行为是不可预测的他们会乱点、会打断操作、会用各种奇怪的输入。我给自己定了一条规矩每设计一条正向用例至少配两条异常用例。这个比例不一定适用于所有场景但它能强迫自己去想这里可能怎么出错。7.4 环境与配置差异引发的假缺陷测试环境和生产环境不一致是常态由此产生的假缺陷非常消耗精力。常见的差异点包括数据量级测试库一万条生产库一亿条分页查询的性能表现完全不同、配置参数超时时间、限流阈值、缓存过期时间、依赖服务版本、定时任务开关、灰度开关。应对方法是在提交缺陷之前问自己一句这个问题在生产环境会不会出现如果答案是不确定就在缺陷单里注明测试环境限定或者需在生产环境复现验证。这样开发在排查时能先排除环境因素。另外一个实用技巧维护一份环境差异清单。把测试环境和生产环境的已知差异记下来新同事上手时先看这份清单能避免大量无效排查。功能测试这件事做浅了谁都能做做深了永远有空间。我自己这些年最大的体会是测试的深度不取决于你用什么工具、写多少用例而取决于你对业务的理解有多透。当你能像产品经理一样讲清楚这个功能的每个细节能像开发一样说出它可能的实现方式能像用户一样想到各种奇怪的用法功能测试才算真的做到位了。