本节书摘来自华章出版社《软件测试价值提升之路》一书中的第3章,第3.2节,作者:杨晓慧编著,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
3.2 正常使用中部分出错
3.2.1 问题案例
我们的产品中遇到的大部分客户问题都属于此类。例如:
某产品的客户端是运行在浏览器上的,支持IE8、IE9、Firefox,但是经常出现某些页面在其中一款浏览器上显示不全或者错位等问题,有个产品由于问题太多,以至于不再支持Firefox。对于移动应用,最常见的是APP在某个终端品牌或操作系统版本上不能正常使用。
某产品新版本逐渐替换老版本的过程中,客户开始使用时都没有发现问题,到某个客户那里突然和原有的功能不兼容。分析发现某个接口字段的合法取值是0~10,产品上一个版本暂时只用了0~5,其他的预留。在新上线的版本中启用了6,触发一个新的功能分支。但是,这个产品是支持客户定制的,客户之前就用了6这个值来触发他们自行定制的一个功能分支。这样,不兼容就产生了。
在日常生活中,我也遇到过某信支付时,付款人已经收到银行扣款的短信,但是在APP上没有交易的信息,收款方也看不到收款提醒。打电话到客服,只告知是系统故障,后台手工处理过一段时间以后,交易数据才恢复。
这类缺陷典型的有:新版本在部分用户那里无法正确升级或使用,新特性在用户进行特别的操作或使用特定的数据时保护不足、出错或造成损失,系统在忙时处理能力不足或出错率高等。
3.2.2 解决问题的思路
【一般处理原则】
产品在使用过程中小毛病不断,一方面会降低用户的满意度;另一方面也会让产品研发不得不投入大量的精力去处理缺陷。如果这类问题经常发生,测试需要把拦截缺陷作为比较优先的任务。
由于解决这类问题需要一个经验和成果积累的过程,所以周期比较长。
【解决方法】
这类缺陷的发现条件是:必须在特定场景下测试,或者使用了特定的数据,或者进行了特定的操作,或者走了特定的路径,总之,测试设计必须考虑到了这些情况。在遇到这类问题的时候,推荐的方法是:1)扩展基本用例集,使之包含安装、升级、应用场景、性能的部分用例;2)形成测试设计要素集,完善测试设计方法。
如果错误经常出现在特定场景,比如安装或忙时,那么需要考虑对测试范围做完善。一般的软件产品,测试中需要考虑功能、性能、安全性、可靠性、易用性等的覆盖。移动互联网应用的测试类型中还有包含安装在内的整个使用过程,以及能耗、组网等方面。
如果错误经常是由于特性的某些影响因素没有考虑到,比如VIP用户、欠费状态用户需要特殊处理等,那么需要考虑改进测试设计,把容易遗漏的测试设计要素(例如上面例子中的用户类型、用户状态)进行归类整理。
判断采取什么手段进行改进,需要依据对客户问题的分析,常用的分析方法是根因分析法(Root Cause Analysis,RCA),通过对缺陷根本原因的分析,找到需要解决的问题,进而确定合适的解决问题的突破点。
为什么没有强调 “使用经典的测试设计方法”
产品在使用过程中有缺陷,肯定会想到改善测试设计,而改善测试设计首先又会想到使用经典的测试设计方法,如因果图、边界值、等价类等。我们的测试团队曾经做过统计,严格要求测试工程师使用这些测试设计方法进行用例的设计,用例倒是增加了不少,但对增加缺陷的发现作用甚微。
进行原因分析后发现,测试没有成功地拦截缺陷,问题并不是出在“测试设计”上,而是出在“测试分析”上。以一个业务流程为例,“测试分析”是画出业务流程,以及各种分支、异常处理过程;“测试设计”是使用深度优先或广度优先策略,实现对图的边、语句、逻辑或路径等的覆盖。大部分情况下,测试没有发现产品的缺陷,并不是“覆盖”的方法不全面,而是在图上根本就没有画出这部分内容。
因此,在测试设计中需要重视“被测试对象分析”:针对需要测试的特性、业务流程、功能(即被测试对象),选择合适的模型表达处理过程、状态跳转、异常处理、逻辑约束、数据结构等,以这些模型为基础进行测试设计,才真正能更有效地拦截缺陷。而在解决方法中提到的两点正是帮助完善“被测试对象分析”的方法。
总之,测试设计方法很重要,但是测试工程师更容易忽略被测试对象分析。
此外,没有正规测试设计过程的探索式测试似乎能够更快地发现缺陷,如果仔细理解常用的探索方法,可以看出这种测试很重视“被测试对象分析”和“攻击”,即通过各种探索方法找到软件各种可能的用法(被测试对象分析),以及通过各种探索方法试探如何让软件出错(可靠性和安全性攻击)。
3.2.3 扩展测试类型
定义测试类型的目的是帮助测试工程师从多个角度对特性或产品的测试范围进行分析。我们的产品中,常见的测试类型包含功能、性能、可靠性、安全性、可服务性、资料;其他测试类型则由产品根据自己的情况选择或者定义。
测试类型一般认为是和ISO 9126软件质量模型一致,但是在实际工作中,测试类型和质量模型并不完全一致,我们产品常用的测试类型有:
功能测试。产品的新、老功能与需求是否一致,各种分支处理是否正确。
性能测试。系统的性能指标,超负载处理能力,长时间稳定性。
一致性测试。产品是否满足相关的标准、规范和法规的要求。
兼容性测试。产品对不同的操作系统、数据库、第三方插件、外部接口、组网环境、硬件平台的兼容性。
可靠性测试。系统从各种已知故障中恢复的过程、影响和难易程度。冗余备份、过载控制等可靠性机制在各种已知场景下是否可靠。
安全性测试。组网设计、访问控制、权限管理、数据保护等安全机制是否能够有效防止安全攻击,并能维持正常运行和保护敏感数据。
可服务性测试。安装升级的过程、影响和难易程度。配置、维护、故障处理等能力是否满足日常维护需要。
资料测试。产品的配套资料能否正确指导安装、升级、配置、维护、故障处理等操作。
体验测试。在仿真、镜像或客户环境中,模拟客户的真实业务场景,对学习成本、操作路径、操作时间、信息呈现方式、界面布局等进行的体验。
互操作测试(IOT)。与不同的第三方设备、不同主流终端设备能否正确地互操作。
实验局测试。新产品或新版本在正式大范围商用前,先在个别客户的真实业务环境下使用一段时间,使缺陷可以更充分暴露,降低大范围应用后的质量风险。
镜像测试。在镜像环境上进行的测试,产品在特定环境下使用,使其所存在的问题能够提前暴露。镜像测试主要强调测试环境的镜像,测试内容可以是功能、体验、可靠性、可服务性等测试类型。这里的镜像是将产品的真实应用环境复制到实验室,环境的复制包含设备、网络、数据、业务、第三方系统等全部环境要素。严格意义上说,是将客户的环境按1∶1的比例在实验室复制,但这样做成本太高,所以更常见的是缩小比例复制,采用与客户环境同系列、但配置较低的设备搭建测试环境。
每个测试类型所测试的大致内容,参见5.2.1节“测试方法和工具方面的能力”。
这些虽然是常规测试内容,但几乎所有产品都测试的只有功能和性能,其他类型测试都会根据产品的特点选择,例如:
平台类的产品。这类产品指公司内部使用的二次开发平台、公共组件等,主要是供公司内部其他产品使用,有时候也可能对外销售。由于不同的产品会将这些平台用于不同的环境和场景,因此这些平台产品需要进行兼容性、可靠性测试。此外,其他产品还需要通过体验测试结果,评估这些平台的学习成本、二次开发和集成的难易程度。
需要遵循标准、规范的产品。在电信领域,针对主要的网络设备都有标准、规范来约束功能、接口、可靠性、安全性等方面。依靠这些标准、规范,客户就可以使用不同供应商的设备,在实现业务的提供、运营、维护的同时,降低采购成本。对于这些产品,必须进行的是一致性测试和IOT。
有较多Web前端或移动APP前端界面的产品。这些产品的用户从Web前端界面或者移动APP进行操作,实现与后台程序的交互。对于这些产品,安全性测试比较重要,此外在前端设计有大的调整时,还需要进行体验测试。
路标版本。指架构层面进行重构或升级的版本,我们的产品一般2年左右会有一个路标版本,这个版本相对前一个路标在DFX多个维度上都有很大的变化,因此,对于这种版本,除了性能,还会对可靠性、安全性、可服务性和资料、一致性、兼容性等进行比较全面的测试。
总的说来,功能、性能、一致性、可靠性、安全性测试在我们的产品中比较受重视。而客户化测试(主要指体验测试、镜像测试、验收测试、Beta测试等有客户参与或者由客户主导的测试)是近年来逐渐被看重的测试内容。
我们的产品中,功能、性能、一致性、可靠性的测试手段和工具比较完整。尤其是功能、性能、一致性测试,自动化程度比较高。这些工具绝大部分也是自行研发的。安全性、可靠性测试的商用工具可选范围比较大,也有免费工具可用,但是不一定真正适合自己的产品;一致性的工具有但是普遍比较贵;功能、性能测试的工具选择比较多,尤其是界面自动化的工具发展得比较成熟。
3.2.4 测试设计要素清单
测试设计要素清单是影响特性表现的各种常规因素。这是根据特性测试的经验总结出来的测试设计辅助工具,这个清单和测试设计方法一起,帮助测试工程师更全面地分析被测试对象。
测试设计要素清单完全是由每个产品经理自行建设,一般测试设计要考虑的要素和产品的数据模型密切相关,因此通常建议产品测试和设计团队共同参与。
【案例】为简易的电商内控系统设计测试要素清单。
这个系统的主要特性和主要设计要素的关联关系如表3-1所示。
此例子是电商的内控系统,该电商在不同电商平台都有网店,每个电商平台都支持PC和移动客户端接入。此系统功能如下:
商品管理。实现商品上架、调价、折扣等操作。
商品订购。实现商品查询、对比、下订单、付款等操作。
商品订单处理。处理客户提交的订单,付款以后启动,至收到货款结束。
商品采购。处理采购单,采购下单以后启动,到货验收,入库后结束。
测试的主要设计要素如下:
用户级别。新客户、常客户、VIP等。
库存状态。充足、紧张、售罄、预售等。
平台订单。电商平台的订单信息。
接入渠道。哪个电商平台,PC还是移动客户端接入。
平台状态。忙、闲等。
其中,商品订单处理之所以与这些要素有关,其原因如下:
VIP客户可以有额外的折扣或赠品,因此在备货的时候会用到用户级别的数据。
商品订单是否能够开始处理决定于库存状态,因此特性与库存有关。
备货、发货时都需要更新平台订单状态,发货以后需要定时扫描平台订单,检查确认情况,商品订单和平台订单状态变化时,可以发短信通知客户。
电商平台处于浪涌冲击(促销)时,不允许查询平台订单状态等操作。
测试设计要素清单并非一个新的测试设计方法,而是作为测试设计的参考信息之一,与测试设计常用的流程图、状态图、逻辑、数据结构分析等方法结合,目的是使测试设计的时候不容易遗漏对输入参数、处理分支的覆盖。以电商内控系统的“商品订单处理”为例,设计的处理流程如图3-7所示。
结合测试设计要素的逐一审查,可以发现“平台状态”处于过载时,可能会导致“同步平台订单信息”操作失败,可能是返回操作失败,也可能没有任何返回消息。无论哪种情况,系统都需要正常处理。于是需对测试设计进行补充,如图3-8所示。
在我们的产品中,测试设计要素清单在新特性的测试设计时完成初稿,在产品上线后通过对客户问题的分析进行补充。
以上介绍的只是解决问题的一种思路。我们的产品中,有一些数据模型超级复杂,不仅测试设计要素多,而且要素之间还要考虑组合,采用上面的思路改善测试设计始终是杯水车薪,无法达到理想的覆盖范围。产品测试团队探索了一个行之有效的做法:随机抽取一段时间的用户操作及其对应的数据,在版本发布之前在实验环境上进行回放,这样一来,现实存在的绝大部分数据组合和业务场景就被覆盖了。对大部分互联网公司而言,这个思路都是一个不错的选择。实施这个思路需要产品做一些工作:系统在处理完任何一个事务后,都需要留下足够详细的记录,测试用这个记录可以还原用户业务场景,形成一个包含预置条件、操作步骤、预期结果在内的完整用例。
3.2.5 客户问题RCA分析
扩展测试类型和优化测试分析,目的都是使以前遗漏到客户的那些类型的缺陷,在以后的测试中能拦截下来。所以,在确定方法之前,需要分析那些遗漏到客户使用时才发现的缺陷,以找到测试过程或方法中存在的薄弱点。
客户问题分析比较推荐的方法是根本原因分析(RCA),这是一种回溯性失误分析方法,包括确定和分析问题原因,找出问题解决办法,并制订问题拦截和预防措施。RCA的一般分析过程如图3-9所示。
在问题发生后,首先通过访谈和资料分析收集尽可能完整的问题信息和数据。然后通过头脑风暴、鱼骨图、因果图、5why等分析方法确定直接原因(问题发生时事物的状态、进行的操作,比如服务工程师误操作)、根本原因(导致问题必然发生的最本质原因,比如操作没有分级权限控制)、间接原因(导致问题发生的其他影响原因,比如操作员是新手)。最后针对分析出来的各个原因制订对应的改进措施,并在措施实施后进行结果的核实和成果的推广。
根本原因分析是一个通用的方法,在不同领域应用时,需要结构化的具体方法,用于解决不同领域的具体问题。
测试进行客户问题的根本原因分析,主要是进行如下调查和追溯:
1)缺陷在项目的哪个阶段被发现,缺陷的触发条件、外在表现和业务影响有哪些。这些是缺陷的背景信息,用于今后确定改进的优先级和设计用例。通常触发条件不明的缺陷,不会进行根本原因分析。
2)缺陷的引入阶段和引入的直接原因、间接原因、根本原因,如何避免引入这个缺陷?缺陷引入的原因可能是需求中缺乏相关信息、代码实现的疏忽、人员交接的遗漏等。通常缺陷都不是测试引入的,追问引入的原因,主要是为了找到问题改进的合伙人。
3)缺陷应该在哪个阶段发现,测试遗漏的直接原因、间接原因、根本原因,如何才能发现?这是测试进行RCA分析的核心,原因可能是需求分析错误、测试设计遗漏、缺少观察点等。测试就是根据这些信息最终归整出改进方法。
4)在分析原因、制订解决措施的时候,尽可能追问到根因,并且针对各层原因确定相应的解决措施。在启动专项改进工作后,还需要根据技术难度、实施成本以及目标达成,确定究竟采取哪些措施、从那一层着手拦截缺陷。
RCA分析中,测试遗漏的根因分析是最关键的环节。在我的经验中,RCA分析首先要注意:追问到技术原因,避免把责任心之类的人为原因作为根因。很多时候需要追问3~5次才能找到真正的根因。
下面以缺少观察点导致了数据不一致缺陷的遗漏为例,说明RCA问题分析和改进措施制订过程。问题原因和措施如表3-2所示。
第一次追问why,得到直接原因,措施可以拦截这个缺陷,但同类缺陷无法拦截,治标不治本。
第二次追问why,得到间接原因,措施可以拦截这个缺陷,也可以拦截同类缺陷,但缺乏可实施性,隔靴搔痒。
第三次追问why,找到根本原因,措施可以拦截这类缺陷,改进彻底且可持续。
进行RCA分析的工作量比较大,因此不可能对全部客户问题进行分析,可以先进行一遍粗略的筛选,选出价值大或者典型的问题进行分析。
3.2.6 提升能力的目的是解决问题
我们的很多产品,都是以这类缺陷的爆发作为测试团队、测试技术建设的契机,因为这时测试工作会比较容易获取所需的人力和设备资源。但是也有不少人在有这个机会时,却把事情做砸了,究其原因,不外乎:
产品对测试的投入长期不足使得测试技术欠账太多,终于质量问题开始失控,让研发团队痛下决心,加大对测试的人力投入。测试经理终于有了喘息之机,把很久就想做的测试设计方法应用、自动化、测试方案模板规范化、DFX测试……一一落实。
那么,问题来了:千头万绪,从哪里开始?要不就是基于最近出现的、客户反应激烈的几个问题;要不就是测试经理有印象的一些问题;要不就干脆不是基于问题,而是测试经理或几个专家个人的技术偏好。具体实施某一项工作,比如测试设计,开展的工作就是组织团队学习测试类型、测试设计方法,制订测试的各种模板,把写的好的测试方案和用例做成样板或案例……,测试团队致力于学会使用标准的方法和模板,使测试终于像一个有技术含量的工作,但是却完全忘了当初为什么要做这些。
最后,在局外人来看,测试团队就是利用这些人,做了最基础的、本来早就该做好的事情,真正的业务问题,并没有思路和行动去解决。
这并不是说不能在这个时间进行基础能力建设,而是说不能止步于此,需要着眼于问题,从问题分析得到解决方案,有能力则补齐短板,最后以新具备的能力为基础,结合其他辅助手段完成解决方案的实施,最终解决问题。这样才算完成了一个问题闭合的循环,如图3-10所示。
3.2.7 预则立不预则废—重视网上问题分析
即使是成熟的测试团队也可能会遇到这类问题。产品被用于新的客户时,由于客户内部组织、业务运营、发展历史、文化等环境不同,产品上线初期几乎都会出现这类问题。如果产品是一个统一版本用于多个客户,遇到这类问题的机会就更大了。
可能研发团队的所有成员,包括测试自己,在遇到这类问题时,都会觉得测试应该可以独自解决这个问题,提升测试设计能力就可以了,因为很多时候,只要测试执行时那样操作了,缺陷是显而易见的。但是真正分析这些问题,会发现当初在测试设计的时候,测试工程师根本没有相应的信息:不知道客户还在用这个型号的机器、不知道客户会这么用、不知道有这种类别的用户等。所以这个问题要改进,很多时候是需要市场代表、系统工程师、测试工程师合作的。
推荐的做法是:持续搜集和分析在客户验收、应用中发现的问题,对问题至少分析到软件设计和测试设计的改进方法,周期性地进行统计。这样,当某类问题比较突出的时候,可以把包括问题、解决方法、需要的协助(这个很重要)、改进后的效果等信息完整、及时地拿出来。
一般开始统计之前确定的分类维度是特性、缺陷严重级别等,这样分类并不利于问题的聚焦和解决措施的制订,建议早期分析积累一定的信息后,采用亲和图法(一种质量分析的方法)逐步形成具有产品特点的分类统计的维度。
通常,在客户没有激烈的反应的时候,研发团队也不会太在意这些问题,但是一旦客户开始投诉,留给改进的时间窗就非常短。所以,建议在产品开始应用之初,就开始搜集、分析客户发现的所有问题,当研发团队没有将问题改进提到议事日程的时候,测试先有信息和方法、工具方面的准备,一旦问题爆发,就能够给出多角色合作解决问题的可行方案。
测试团队既要重视测试设计,也要重视客户问题的分析,这是测试最重要的两个手段,无论是个人能力提升,还是团队技术积累都要用到。