移动测试开发 领略项目测试的艺术:从需求评审到测试执行的实战经验分享
业务测试是测试人员的基本功,想要有扎实的功底,除了不断地学习、实践,还需要阶段性地回顾、反思。在本文中,笔者总结自身项目测试的经验教训,与大家一起探讨日常业务测试中较为关键的 3 个环节,包括需求评审、用例设计及评审、以及测试执行。
需求评审
熟悉需求、确认测试范围和重点,是业务测试的第一关。下面,介绍一下我摸索出的一些方法和注意事项。
1. 熟悉产品写出的需求
拿到需求,从头到尾读一遍,熟悉需求的同时,注意找出没有理解或有明确错误的内容。
♢ 模糊的逻辑;
♢ 不清晰的交互、难以理解的名词;
♢ 不一致的处理方式;
♢ ......
2. 思考产品未写明的需求
除了产品明确写出的内容,我们还要反观文档,发掘其中未写明的需求。
■ 产品文档的遗漏
♢ 同类逻辑被省略;
♢ 边缘逻辑或场景被遗漏;
♢ 关联功能未说明;
♢ 性能要求缺失;
♢ ......
■ 隐性的需求
♢ 想要发现隐形的需求,需要我们在读通需求后,跳出文档,进行创造性地思考。
案例:
• 需求背景:实时数据展示页面,后台以 5 分钟为间隔,将过去 5 分钟的数据加工后存放到库里,每次刷新页面时,会展示库中最新加工后的数据;
• 隐形需求:前端如果没有操作,展示的数据不会随着时间更新。为了优化使用体验,前端可以设置一个定时器,每 5 分钟调用一次接口更新数据,保证有新数据产出时,即使不刷新页面,也会展示最新的数据;
3. 明确测试范围、核心需求和边缘需求
■ 明确测试范围,避免 case 设计时出现遗漏。
♢ 特别是历史功能修复或优化的需求,容易出现关联场景遗漏的情况;
■ 明确核心需求和边缘需求,可以方便在后续 case 设计时恰当地分配精力,在测试执行过程中,也能更好地权衡问题跟进力度,有利于保障用户常用功能和关键功能;
♢ 除了需求中重点描述的关键功能之外,一些简短的需求点也可能是系统的重要功能。针对这类需求,也应当分配更多的时间、精力在 case 设计上,以保障功能的易用。
♢ 为了做好这一点,首先在熟悉需求后,要站在用户视角,留心思考。其次,还可以与产品多加沟通,明确用户常用功能。
案例:
• 需求背景:账户消费数据展示列表,用以给管理者展示账户的消费情况;
• 需求文档:文档将大量篇幅用于描述系统交互和指标计算逻辑,对于排序功能仅指出了需要排序的字段,无详细要求。
• 实际情况:管理者经常需要使用排序功能来查看关键信息,同时排序与其他组件的交互较为复杂,因此需要投入较多精力来设计用例。
4. 注意事项
■ 尽快完成,留出缓冲时间
♢ 越早完成,越能避免研发实现偏差的情况发生;
■ 统一确认,减少沟通成本
♢ 分散确认增加沟通成本。统一确认有利于节省双方时间,尤其是对于产品同事同时跟进多个需求的情况下,统一跟进可以避免精力反复拉扯的情况发生;
■ 推进修改,持续优化需求
♢ 一旦确定了需求有模糊、缺失或错误,要罗列清楚、并积极推进修改。
♢ 为什么要落实需求的优化和修改呢?
• 首先,模糊的需求可能导致团队内部难以对齐,在项目后期带来返工延期,甚至是上线隐蔽问题的风险;
• 其次,有时会碰到研发同事严格按照需求文档实现系统功能的情况,口头达成的共识不可靠;
• 此外,后期需要回顾需求时,重新确认浪费时间;
用例设计与评审
1. 用例设计的基本思路
①. 按照黑盒设计方法,分区、分类覆盖需求点。
■ 设计方法。主要包含:边界值、等价类、场景法、因果图、判定表等。
■ 功能分区。以一个最简单的功能列表为例,大致分区为:权限、查询、列表、导出等。
■ 用例分类。根据实际情况,可考虑以下几类用例:基础功能、易用、兼容、性能、安全、容错、冒烟、回归、线上验证等。
②. 依据分层测试思维,对用例进行检查,补全。
大致分层:前端、后端、中间件、数据库。
■ 前端:主要考虑界面及交互细节、接口调用等。
♢ 以接口调用为例,主要检查每个操作是否调用了正确的接口,是否多调或少调了某些接口。
案例:
• 需求:上面提到的实时数据展示页面,包含列表和饼图两个维度的统计数据,支持查看从当日零点到当前时间或整点时间的统计数据;
• 场景 1:指定查看当前时间的数据,对列表进行排序操作;
• 测试点 1:排序操作调用了列表的接口,使列表获取到了最新的数据,并依据最新的数据排序后展示。因为查看的是实时数据,为了保证两个模块数据的一致性,所以需要同步调用饼图的接口,更新饼图展示的数据;
• 场景 2:指定查看整点时间的数据,对列表进行排序操作;
• 测试点 2:排序操作调用了列表的接口,列表仅更新了排序的结果,本次调用和上次调用获取的数据并没有改变,所以不再需要同步调用饼图的接口更新数据。如果此时也调用了饼图的接口,那么会带来额外的性能压力;
■ 后端:主要考虑后端对业务逻辑的实现。
♢ 放在白盒测试部分介绍。
■ 中间件:主要考虑业务逻辑与中间件的结合。本文以消息队列为例:
♢ 常规用例:
• 上游消息的触发逻辑是否正确;
• 上游发送的消息体字段是否完整、正确;
• 上下游要求的字段格式是否一致(如上游传递格式为 int32 的字段,下游当做 int8 处理);
• 下游消息的处理逻辑是否正确;
♢ 进一步思考可补充的用例:
• 下游处理时是否做到了消息幂等;
• 判断幂等的逻辑是否合理;
• 是否有重发机制;
• 重发机制是否可正常使用等;
■ 数据库:主要考虑后端与数据库的交互和数据准确性。例如:
♢ 数据库操作有没有添加事务控制;
♢ 有新增字段时,字段的格式是否符合需求,是否有超长截断,或插入失败的风险等
③. 针对特殊场景、关联场景,进行用例的检查、补全。
■ 特殊场景。例如:
♢ 快速连续重复操作;
♢ 从内存中读写时是否需要加锁;
♢ 脚本间的执行顺序;
♢ 上下游执行操作的顺序等;
♢ 异常报警机制;
■ 关联场景。交互或逻辑复杂的系统,操作的影响范围广,需要考虑是否有关联的影响在 case 中没有体现。
④. 结合白盒设计方法精简用例,以及补充用例。
■ 设计方法:基本路径测试,逻辑覆盖等;
■ 精简用例。例如:
♢ 进行更加准确的等价类划分,删除掉冗余的等价类;
♢ 明确代码中逻辑判断的依据,不用再考虑关联因素的影响;
♢ 确认公共逻辑,不用重复测试抽离出的独立函数或接口。同时,如果多个功能存在相同的逻辑,但在代码中分别实现,这时要避免出现测试遗漏的情况;
■ 补充用例。阅读代码,检查是否存在遗漏的验证点,例如:
♢ 代码计算
• 是否可能出现算术溢出;
• 浮点数精度问题(如:1.23*100 != 123);
• 判断的逻辑是否合理、是否存在遗漏或多余等等(如:研发增加了需求中未提及的判断条件);
• 判断条件是否在各种情况下均可用(如:使用数据库中的字段 A 进行条件判断,但部分记录缺少字段 A);
♢ 数据库操作
• 查询的表、字段是否正确;
• 联表的方式是否正确(如:应该用 left join 的位置,使用了 inner join 导致查询出的数据范围缩小);
• 新增数据库记录时,数据格式是否正确(需求:将浮点数四舍五入转为整数后入库。实现:把浮点数当作整数直接入库,导致小数部分被截断,仅实现了” 四舍 “,没实现” 五入 “);
♢ 其他
• 异常报警机制是否合理、完善(如:重要业务应当采用持续报警机制,而不是单次模式);
2. 用例评审的工作项
用例评审时,除了常规的评审外,还可以做以下的工作:
• 针对三方未对齐的需求细节,自身对于需求的疑惑,在评审时进一步确认;
• 与研发探讨实现方式、变动范围,挖掘潜在的风险点;
• 了解可测性。针对常规方法不可测的内容,讨论是否有其他测试方式,并争取研发的合理协助,例如打印更清晰、全面的日志,单独编写专供测试使用的接口等;
• 明确产品期望的准出标准。判断是否有冗余的测试内容,或遗漏的测试内容;
• 确认排期。遇到排期超出预期的情况,可以考虑增加测试人员、提前提测部分内容、或延期部分需求;
测试执行
为了做好测试的具体执行工作,可以关注以下几点:
1. 尽早找出关键问题
测试不可能发现全部的问题,在时间有限的情况下,测试工作最重要的意义是保障产品达到质量的底线,想要做好这一点,关键之一在于尽早找出系统中潜在的关键问题。
①. 尽早发现关键问题依赖合理的测试安排:
■ 恰当的测试安排:
♢ 测试准备。在正式测试之前,需要先做好测试前的准备。例如:
• 熟悉关联的业务逻辑,如上游造数流程;
• 熟悉测试用到的库、表;
• 准备好测试环境;
• 准备好测试数据;
♢ 冒烟测试。主要是准备好冒烟用例,提前提供给研发同事,并在提测后严格执行;
♢ 第一轮测试过程中,需要注意:
• 首先测试核心功能的核心场景,然后测试边缘功能及边缘场景;
• 这个过程中,对于发现的关键问题,随时与产研沟通;
• 对于模糊或边缘的细节问题做好记录,一轮结束,统一与产品确认是否有必要修改。
• 细节问题如果没有明确需求,不要依赖直觉判断,应当先与产品同事确认后再提 bug,避免出现研发同事需要反复修改的情况。
♢ 第二轮测试过程,需要注意:
• 首先,整体回归,重点回顾一轮出现问题较多的功能;
• 之后,重新审视需求和 case,检查验证是否有遗漏;
• 最后,还有时间的情况下,适当开展随机测试,可以发现一些想象力之外的问题;
■ 合理测试安排的达成并不是那么容易,实践中可能会出现下面的问题:
♢ 难以避免的个人习惯和偏好。例如:
• 严格按照 case 编写顺序进行测试;
• 习惯按照功能区域划分进行测试;
• 喜欢先测熟悉的模块,把陌生或者难以走通的 case 留到后面等;
♢ 边缘场景的遗漏。可能原因:
• 轻视边缘功能和场景;
• 时间精力不足,造成遗漏;
♢ 应对方案:
• 达成更加准确的测试估期;
• 分清主次,做好 case 执行记录;
• 养成好的测试习惯,安排每日测试计划时,依赖理性判断;
• 测试中期,要停下来想一想,有没有偏离原定的测试重点?测试重点有没有发生转移或需要矫正?
• 测试后期,要停下来想一想,核心功能是否已经得到保障?有没有出现越测越窄的情况?边缘功能有没有遗漏的发生?
②. 尽早发现关键问题还要利用好两个测试人员的优势:
■ 优势 1:对于需求和实现的了解。
♢ 做好测试左移可以扩大这个优势,帮助我们更好地判断核心功能是否符合产品设计;
■ 优势 2:对于潜在问题的敏锐度。
♢ 随着经验的积累,对于可能出现的问题能有更加及时、准确的判断。
2. 更好地执行测试
实际的测试执行过程中,为了有较好的测试效果,我会注意以下几点:
■ 严格落实用例执行。
♢ 保障全部用例得到执行并通过,是最基础的工作内容;
■ 不断补充测试用例。
♢ 随着对被测系统和实现逻辑的了解加深,可能会发现一些遗漏的测试项,应当及时记录到用例当中,不要让灵感一闪而过;
■ 结合日志、代码开展测试。
♢ 测试前简单通读代码,测试过程中,结合具体的日志、代码,实现更加精准的测试。好处有:
• 结合日志信息,尽量定位具体问题,可以节省沟通成本;
• 查看研发对于问题的修复,判断问题原因和回归的范围;
• 开展推断式测试。以 sql 为例,针对待测逻辑,先按照自己的理解写一遍 SQL,执行后与系统进行对比,在发现出入后,找到对应的日志和代码,观察研发如何取数,思考并跟进其中的差距。
■ 使用分层测试思维。
♢ 用例设计时已经采取了分层思维,执行时结合已有 case 进行拓展测试即可。例如,关注前端各种情况下的入参是否合理;
■ 采用脚本提效。
♢ 编写脚本可以帮助实现更好、更快的测试。项目中可以采用脚本提效的机会还是很多的,关键是具备编码能力,并及时意识到可以通过脚本更好地解决面临的问题。
3. 写好 bug 描述
■ 为什么要写好 bug 描述?
♢ 好处 1:一个好的 bug 描述,可以使得研发的工作效率更高;
♢ 好处 2:bug 描述是团队成员对我们工作印象的一大来源。好的 bug 描述,可以赢得更多信任,而这种信任又可以转化为支持和影响力。
■ 怎么写好 bug 描述?个人的经验教训有下面几点:
♢ 经验 1:要确保提出的 bug 完整准确。想要认清一个问题的本质并不容易,不要在发现 bug 的第一时间就提交;
♢ 经验 2:要包含必须的有效信息。测试数据,请求参数、接口返回,复现的关键步骤等等信息决定了研发是否能真正理解我们的 bug。捕捉到问题的兴奋感或精力的过度消耗,有时会让我忘记填充足够的信息;
♢ 经验 3:要提炼关键信息。有时候为了把问题描述全面,bug 中记录了过多的信息,这样反而容易让研发捕捉不到关键信息;
♢ 经验 4:更进一步,还要提升个人技术,争取提供更多定位上的帮助;
4. 及时的风险预报
随着项目的推进,潜在的风险可能会逐渐显现,发现后我们需要足够警觉,尽快做出处理。可能的风险:
♢ case 设计覆盖不全;
♢ 研发技术方案变更;
♢ 研发对于需求理解的偏差;
♢ 需求存在的遗漏或不合理;
♢ 种种情况导致的进度延迟;
♢ ......
结束语
在日常工作中,并没有固定的最佳实践。我们做出努力,只是为了在工作中碰到各种情况时,都能结合实际,找出更好的处理方式。
最后,以上分享内容是笔者针对近期项目的反思总结,个人的经验总有局限性,欢迎大家指正和补充。