质量保障是做好产品十分重要的一步,但是为了快速起项目形成业务,很多项目在设计之初全由前后端开发人员自测,稳定上线后才补上质量保障侧的内容。本文旨在梳理一套BS架构产品的通用质量保障模型。

产品设计与技术评审阶段

在设计阶段,QA应当在各评审会1小时前开始阅读并评论方案,以此提高会议效率并尽可能发现其中问题。

产品定义文档(PRD)评审/用户体验设计(UED)评审

在此阶段,开发(RD)与测试(QA)人员应当替PRD/UED捉虫,寻找PRD/UED当中的缺漏和未定义行为。在开发之前就尽量完善PRD到RD、QA没有疑问。举个例子:

需求名为“为搜索框增加搜索历史记录与搜索建议”,PRD中没有显式说明该需求的“记录的历史记录”是点击搜索按钮、按下回车哪一种方式触发;也没有说明搜索历史记录记录的是用户所有搜索行为还是仅记录用户点击搜索建议后产生的搜索行为。这样RD可能会理解/曲解PRD,只记录点击搜索建议以后的搜索关键词。显然从用户视角这样的产品很奇怪,但是从RD视角来看“反正PRD这里没定义,怎么好做怎么来呗”。这样的厚度哦就是功能做出来PM发现和自己想的不一样,用户用起来不爽。如果在需求评审阶段就能解释清楚需求定义不明确的内容,这种问题就能大大减少。

一些常见的思考发散方向为:

方向名发散举例意义
权限控制这个需求不需要做权限控制吗防止需要控制的功能PM忘记做权限控制,或新功能需要收缩权限但是忘了或者没注意
数据这个需求埋点设计成这样是不是不合适埋点放在哪里、怎么触发才能达成PM的需求,收集到他们需要的数据需要一定的前端常识,而PM不一定有相关技术积累
交互逻辑当用户没有某某权限时,这个按钮是否需要置灰有些小需求没有UED直接参与,一些展示逻辑PM想的可能不会很全,需要问清楚
边缘案例当子节点数量太多,这个页面下半截会全部被子节点遮挡,要不要加个max-height同上
设计过于复杂/简单这个功能可以通过和某某现存功能集成的方式实现,不单独开一个页面是否可行?(反之亦然)否则实现成本会太高/维护成本会太高PM可能不会考虑技术上可以通过耦合/解耦合降低系统维护和开发/测试成本

值得注意的是,除非需求太离谱,**不要轻易质疑PM这个需求有什么意义**。我们研发人员如果没有去和用户做调研,不知道客户在想什么就去拍脑袋抢PM的工作只会让PM觉得你很烦。

技术评审

一般而言PM不具备很强的技术背景,技术评审中PM会难以捕捉RD设计的方案中可能与PRD不同的地方;因此QA作为技术人员,应仔细评估技术方案能否覆盖整个需求。有研发相关知识的QA更应当就自己理解的技术难点向RD提问来提前暴露排期、技术设计中的漏洞。一些常见的思考方式有:

方向名发散举例意义
性能接口这样设计有可能性能不足?这样改接口对性能有多少影响性能应当是后端考虑的重要问题,但是如果他们没有考虑,QA要替PM问道
数据安全这些东西放在local storage是否合理,会不会导致泄露或权限控制失败?防止RD实现的时候只考虑实现难易程度,不考虑安全性
实现建议最近在推行自动化,请在代码中添加ID等识别符方便QA定位元素给前端元素加id、给后端代码加探针都是对前后端没有直接意义但是对整个产品质量保障有重大意义的事情。
边缘案例当子节点数量太多,这个页面下半截会全部被子节点遮挡,要不要加个max-height同产品方案评审

测试用例评审

测试用例评审的最重要目的是告知RD哪些测试用例需要在交付QA前自行测试完成——这些测试用例被称为“自测用例”;其次,测试用例评审中团队内其他角色可以站在他们的视角上为QA提供更多思路完善测试用例。自测用例的作用是为研发交付测试的产品设置准入门槛,防止研发写了一堆bug以后自己也没试过就直接丢给QA,消耗QA过多人力做重复而无用的工作。自测用例应当覆盖该功能的所有核心要素和最直接影响用户体验的界面组件。但是,自测用例不应该超出PRD显式定义的范畴,覆盖过大面积的自测用例会让RD心力憔悴,也会降低RD充分自测的意愿。

研发阶段

研发阶段QA参与相对较少,主要由RD遵守预先设置的质量保障规范来保障前期质量。当然这不意味着在需求开发的时候QA没事情做。QA一般可以在此时完成已上线产品功能的自动化覆盖、巡检和其他未完成的质量管理流程建设。

代码规范

严格遵守PEP; 使用TypeScript替代JS;使用ESLint并致力于消除绝大多数error/warning;正确命名变量并在弱类型语言/动态类型语言中主动使用类型定义等代码编写策略都可以减少意外的问题。一般而言公司会有编写代码的标准流程,团队应在自身实际情况的基础上修改、优化规范并努力执行。

单元测试

单元测试是测试单个函数逻辑是否正确必不可少的部分,单元测试一般由RD团队编写,并尽可能覆盖功能的每个函数。做单元测试时,所有数据全部使用假数据(Mock),所有用例跑在本地,着眼于单个函数内部逻辑而非多个组件之间的联系。

单元测试一般应占到开发实践20%以上.

集成测试

在交付QA前,RD应当根据自测用例列表将集成好的前后端试用、测试一遍。这一过程可以手动进行,也可以通过运行已有的自动化测试用例作回归,只对增量手动测试。

集成测试的自动化可以考虑QA与RD共建,RD做最低限度的、仅包含自测用例的集成测试;其余边缘、发散用例由QA自动化。

代码审查

代码审查不仅要做,还应该好好做。交叉代码审核有利于找出低级编码错误、统一代码风格、严格落实编码规范。这一过程主要在RD内部进行。

测试阶段

测试阶段QA应按照基本的工作规范完成端到端手工、自动化测试。根据测试情况对项目做质量评估,决定是否能交付PM验收或是否拒绝RD提测。

拒绝RD提测一般由于过多测试用例失败或核心流程没走通就提测。

上线流程管控

代码在本地跑的通不代表代码上线能跑,QA验收了也不代表真的发现了所有的bug。因此,上线流程管控是必不可少的。在上线流程中,QA和项目组长可以通过一些自动化或流程管理手段减少或消除上线风险。

CICD

现代软件开发流程为了减轻编译上线中的重复劳动一般都会配备基本的持续集成开发流水线,在流水线中,我们可以通过添加自动化测试和手动确认卡点来进行各类上线前的检查。

可能你会问,我们之前做了很多手工和自动化测试了,有必要在临上线还要做卡点检查呢?答案是有必要——一个迭代不会只做一个需求,而测试阶段每个需求是独立测试的。在上线过程中涉及到代码合并、配置文件增删,很有可能出现牵一发而动全身的问题。在这个阶段,我们可以通过下面的节点来增强稳定性

  1. 自动化回归测试节点
    在这个节点,我们通过运行已有的API自动化、UI自动化、Diff测试、压力测试脚本检查本次上新的功能有没有影响已上线逻辑、有没有导致线上性能劣化。
  2. 小流量/灰度测试
    当自动化测试没有发现问题,对于多机房/多集群服务,我们可以先在一个机房的一台机器或部分机器部署服务并在前端实际体验一下新旧业务的核心流程是否出现问题。人在流程中永远是最后兜底的角色。

线上质量管控

线上质量管控指的是QA和RD针对已在线上的服务设计的服务稳定性监控。除了对本产品的逻辑进行监控,这种监控还有助于发现由于依赖服务未告知即变更带来的线上问题。

巡检

API自动化、UI自动化、Diff测试都可以设置定时巡检。定时巡检的目的就是帮助及时发现依赖服务、基础服务变动导致的自身业务崩溃,避免在大量用户反馈无法使用服务以后才后知后觉,产生巨大影响。巡检的建设中,API自动化和API Diff测试应当为首要建设目标——它们建设简单,收益巨大,也可以作为QA了解本产品所有接口的最好切入点。

相比侵入性较小的API自动化,性能测试一般只在用户量较低的时段、在部分机房周知各个依赖方的情况下进行。这样操作是为了避免对上下游产生不必要的压力,也为了防止压测时用户量居于高位,影响用户的体验。

UI自动化有其自身特点——UI改动一般较为细致,也较为没有结构无法预测改动,因而建设优先级相对较低。

稳定性监控

稳定性监控可以通过关注时段内日志聚类(接口调用成功率、服务报错数)、资源监控(服务器资源占用情况)等服务数据波动情况来尽早发现可能存在的问题。常用的指标有:
链路完成速度同比、常见错误数量波动、服务调用数跌零/过低/过高、业务数据(如走某个业务分支的请求数占总请求数比例)跌零/过低/过高、QPS跌零/过低/过高等

质量保障标准

QA的另一个关键工作时制定质量保障标准。服务不可能永远不出错,出错后的应对措施必须再出错前就决定好,才不会在出错后无所适从。QA需要建设的质量保障标准一般有测试用例标准、提测准入标准、bug修复流程与时效要求、线上事故定级标准与复盘流程等

测试用例标准

指的是QA编写测试用例的方式方法和基本结构、不同优先级的用例划分的标准。

提测准入标准

指的是达到何种标准,RD可以交付产品到QA进行测试。一般而言要求100%自测用例通过方可提交测试。

bug修复流程与时效要求

指的是不同优先级的bug要求的平均响应时长、平均问题定位时长、平均修复时长及无法及时完成时的升级流程。

线上事故定级标准与复盘流程

事故定级标准指的是线上事故的定义方式、发生线上事故时的定级定损标准与事故响应流程、时效要求。

事故复盘流程指的是线上事故解决后如何进行事故根因追查、工作流程优化(以避免同类事故重复发生)