作者介绍
去哪儿网测试开发专家——鲁国宁
TakinTalks社区专家团成员。2019年加入去哪儿网,负责测试流程的治理和测试工具建设。主导/参与建设的平台有自动化测试、全链路压测、代码覆盖率、Mock平台、智能推荐等。曾先后就职于京东商城、海尔集团等,擅长性能压测平台建设,并实现近亿级QPS压测,曾多次为618、双11等重要活动保驾护航;
温馨提醒:本文约4500字,预计花费8分钟阅读。
背景
作为一家出行旅游服务平台,去哪儿网的搜索页面功能非常多且复杂。以机票搜索场景为例,用户的搜索场景包括乘机人、起降地、仓储等信息。此外,还会关注航司信息、起降地点是否需要中转、落地时间和后续出行安排等。搜索结果出来后,用户还会进行后续操作,比如搜索航班价格,选择退改服务、出行保障、接机服务和住宿服务等等。
如上图,QA需要准备的Checklist高达1万多条,每条Checklist对应至少1条测试用例,还需确保用例的时效性。随着业务的不断扩展,返回结果数据呈现不断膨胀的趋势,测试同学还需要确保各种数据的准确性,包括渠道、价格、乘机人和服务包等多个维度的数据。
因此测试同学每天需要忍受大量繁重且单调乏味的工作,这对于他们的精神和体力来说都是一种折磨,伴随而来的就是发布故障居高不下。
(整体发布故障偏多,功能故障占比50%)
秉持着用技术改善业务痛点的理念,去哪儿网不断完善工具平台的建设。根据公司发布的数据显示,去哪儿网过去一年中,发布故障数和故障率都不断降低,并始终保持在4‰ 以下。开发和测试的比例也不断变化,从之前的1:1降至测试占开发的1/3。因此,本次分享的功能测试左移,希望能够在降低成本、降低故障率、提高研发效率等多个方面为大家带来一定的帮助。
(近一年发布故障数、开发测试比例不断降低)
一、如何通过自动化测试降低成本?
1.1 整体思路
在工作中,测试同学担任承上启下的重要角色。在项目周期中,测试工作占据了近一半的成本,所以降低人工测试成本是一个重要的目标。我们通过数据分析,发现测试同学在验证核心功能时,人力成本主要分为三个部分:用例准备、环境准备和结果断言。其中,Checklist和用例准备占据了50%的比例,需要特别处理。环境准备需要确保发布代码的一致性,而结果分析需要关注每个细节差异,确保结果的正确性。为了解决这些问题,我们决定采用自动化测试平台来代替繁琐的手工工作。
通过自动化平台实现用例维护、部署以及分析断言结果。让测试人员能够专注于差异测试,不被回归测试烦扰。
1.2 自动化平台建设
1.2.1 方案选型
在方案选型中,最具挑战性的是用例的运维。为了达到全面覆盖和充分测试的目标,我们需要考虑两种方案:一种是基于覆盖率,另一种是自己维护Checklist。
1)覆盖率的原理
代码覆盖率原理是在每一行代码后面插入探针Flag,默认值为False;用例请求路过代码时Flag的标识会标识为True,这些Flag值就是代码覆盖率的数据,根据Flag的状态判断代码是否执行。
自动化平台使用代码覆盖率方案时,要做到覆盖全面的业务,需进行大量的用例回归验证;每执行一次用例请求后收集一次覆盖率数据;此时通过判断覆盖率数据是否增加来判定是否走到了新的代码。
此方案在执行大量用例与覆盖率收集过程会消耗较多时间,因此具体落地是需要在每天凌晨执行昨天的数据,计算并保留有效用例,供今天的自动化测试使用;伴随的一个运维痛点是,当凌晨业务异常时,不易及时定位修复,因此影响第二天的自动化现象会偶尔发生。
2)Checklist的原理
Checklist的原理是用户只配置用例维度(如:航班类型、乘机人类型等),维度的值不需要配置,在业务日志中自动拉取获得,然后多个维度自动叉乘出Checklist。例如,9个航班类型、5个乘机人类型、120个服务项目会自动生成 9*5*120=5400个Checklist。有Checklist就需要找对应的用例,基础架构的TC同学,实现标准化接口日志,所有的业务应用均可打印请求参数、返回结果等信息,自动化平台在此日志中基本满足用例生成需求。
3)方案对比及结论
对比这两种方案,我们可以发现,第一种方案是业务维度的展示,覆盖率的方式只能看到代码是否走到,无法知道每条Checklist的维度值,因此无法展示或查看每一条Checklist的覆盖度情况;同时,此方案对覆盖率平台有依赖,在实践过程中会导致覆盖率平台Load偏高,甚至系统异常的可能性。此外,用户对数据时效性会有所吐槽,因为它是在当天凌晨执行,不满足互联网企业追求时效性的诉求。
相比之下,第二种方案会根据用户配置、线上日志实时更新Checklist,在当前数据以及历史数据中捞取对应的用例。当找不到时,会有历史用例的补充策略来填充。因此,Checklist方案可以满足观测性高且无延迟的需求的。
最终,经过业务线和技术委员会的评审,我们选择了第二种方案。
1.2.2 实践过程
实践过程可以分为三个阶段:触发、执行和报告。
第一阶段,即 Step 1,是触发过程。以前,QA同学和开发需要进行一定沟通后再点击提测。现在只需监听开发Push的代码或项目状态的变化(比如点击了提测),就会自动触发部署。第二阶段是执行阶段,Step2 会准备环境和用例信息;Step3 将用例分别在基准环境(线上代码)和测试环境(本次开发代码)上执行。Step4 主要功能是结果断言,这里将基准环境作为参照物,与测试环境执行的结果进行 DIFF。最后将结果(成功、失败)以邮件和通信工具方式周知到对应人。
1.2.3 实践难点/要点分享
难点1:生成Checklist 和用例
在业务自动化平台实践中,生成Checklist 和用例是最困难的模块。这里有一个维度名的概念,可以理解为测试传入的参数Key,比如航班类型、乘机人类型、成人/儿童数量等。
用户需要初始化维度名字段,字段值可以在线上自动补充(当然用户可以写成固定值)。有了测试维度,就可以叉乘出 Checklist,例如航班类型、乘机人类型、起降地点就会叉乘出指数级的 Checklist。有了 Checklist,就可以展示每个 Checklist 的覆盖度情况,并提示无效的 Checklist(如图所示)。
这样,我们就实现了只需要配置维度名称就能自动生成 Checklist,再根据线上标准日志数据生成用例信息,至此完成了最基本的Checklist与用例诉求。
要点2:业务变化时Checklist如何自动调整
虽然我们已经能够自动生成Checklist ,但是Checklist 会不断变化,因为服务一直在变化,例如航班类型会不断新增、缩减等。
所以,当遇到新增情况时,我们会从 TC 的标准日志中解析对应的字段,当发现新的值出现时,平台就重新生成新的Checklist 和用例。当航班或航线消失时,平台会判断该 Checklist 的用例最后一次生成时间,如果在设置的2周内没有生成该 Checklist 的用例,我们就默认该条用例是无效的。当超过一个月时,平台会自动删除该条用例,当然也可以手动一键删除。这样,从维度名、Checklist自动调整 ,再到用例自动完善,就形成了一个自动运维的闭环。
要点3:部署与触发中的高效率
在部署阶段,主要涉及基准环境和测试环境的部署。
环境代码介绍:基准环境作为参照物,需要实时与线上环境同步,实现此能力只需监听线上应用发布的消息,自动发布即可完成,达到用户不再关注基准环境的要求。对于指定的测试环境,平台检测开发Push 的代码是否与环境代码一致,即环境发布代码 与 Git 分支 Commit 的SHA值是否匹配。若不一致,则触发部署,反之跳过部署。
并行开发难点处理:多项目并行开发时,使用一个测试环境就会出现串行发布与测试等待的问题,因此去哪儿建设了软路由环境(也称泳道环境)。在基准环境(部署线上代码),一个项目需求创建一个软路由环境,软件环境上的应用部署项目对应分支代码。测试请求携带软路由标识,请求路过修改应用时,走到软路由环境,反之路过非修改应用时走基准环境,这样就解决了同一个应用并发项目开发的难题。联调场景也是一样,多个应用使用相同代码分支默认使用同一个软路由环境,联调过程更加方便,建议流程图如下。
如图所示,在软路由环境01中,我们拉取了 B1 和 D1 分支,这样就可以在软路由环境中测试它们的分支,减少了等待时间。
要点4:断言结果要多、分析维度也要多
结果断言与报告展示是自动化平台建设的最后一公里,容易被开发同学忽视,然而用户会根据最后的结果来评判平台的好坏。在此,我们主要考虑两点:一是测试的判断维度要多,二是返回内容的断言要准确。我们的测试维度包括覆盖率、数据增量和全量数据。此外,我们还有一个分析的维度,例如,我们可以按照航班类型对结果进行分类,以便快速定位问题。
还有一个维度是结果分析,我们会对每个 Case 执行并检查结果是否符合预期。底层使用的原理是权重相似度匹配,即每个叶子节点作为一个权重,层次越深,权重越小。我们做了大量的工作,支持了复杂的自动判断和用户自定义的断言逻辑,包括增加、缺失、变更以及正则表达式等特殊条件的断言。
1.3 实践效果
自动化测试平台落地后,我们回归测试时间从原来的至少0.5天降到平均不超过5分钟,且不依赖于人工干预,完全后台自动运行。总项目中QA的排期占比,也已从近45%降至15%。
二、如何通过智能推荐降低故障率?
2.1 支持的功能
自动化测试落地虽然降低了故障数量,但回归测试仍不能完全满足公司要求的低故障率。经过一个季度的数据分析发现,代码变更和配置变更是故障的主要来源。针对代码变更,测试未覆盖或未发现异常是导致上线出现故障的重要因素。针对配置变更,线上动态配置通常是先配置再观察,因此配置异常引发的故障时常发生。在应对配置变更引发线上故障问题时,我们建立了自动化拦截机制,通过将配置在仿真环境执行自动化测试方式,来校验配置是否存在风险,自动化测试通过后配置再自动同步到线上,从而大大降低了配置变更引发的故障。然而,应对代码变更引发的故障,我们需要一个新的平台来解决。
这里,基础平台搭建实现精准测试和异常检测,统称为智能推荐平台。公司希望测试结果既准确又高效。这就需要在根据变更代码进行测试用例推荐时,进行精准的匹配,使用最少的用例来请求变更方最全的分支路径。此外,当在线上出现异常时,需要及时发现并提示用户,特别是当异常信息牵涉到变更方法时。
2.2 智能推荐平台建设
2.2.1 方案选型
在精准测试中,我们需要找到请求参数与代码方法的关联关系,为此收集了三种方案,分别是AOP、TC同学开发的Java-agent以及代码覆盖率平台。最终,我们选择了覆盖率这种方案,因为它能够精准到行,并能区分方法内的分支路径(if条件路径),满足业务线要求的方法测试充分的要求。方案对比如下
2.2.2 实践要点分享
1)整体架构
我们的整体架构可以分为三个部分,其中中间部分是比较重要的。整体可分为两个业务流程。第一个业务流程是保存用例和代码的关系,即入库的过程。我们使用一个Job来定时从线上获取请求并收集覆盖率,然后进行去重分析,最终将代码与对应的用例关系保存到数据库中。第二个业务流程是推荐。当开发同学Push代码时,我们会识别变更的方法,并将库里的代码用例推送给他,执行后将结果也推送给他。在执行过程中,如果出现异常或识别异常,特别是与变更方法相关的异常,我们会及时通知用户。
结合以上架构,下面我们将介绍一个实践过程。
2)精准测试
第一个要点是精准测试,这需要对特殊包进行过滤,我们举例来说,去哪儿网只需要收集com.qunar包路径下的数据。此外,对于一些异常无效的变更,例如添加日志或监控,可以自动过滤掉。
第二个要点是测试全,主要是针对变更的方法,它的if-else条件要全面测试。我们可以看一下覆盖率原理。在每一条指令下都插入了一个探针。例如,第一个请求到达并走了探针1、3,第二个请求走了探针1、4。但是第三个请求走了探针1、3、4之后,我们仍然会收集它,因为它的链路与前面的探针1、3和探针1、4不同,所以我们会将其收集到数据中。当然,如果又出现一个请求走了探针1、3,就会出现重复数据,我们会过滤掉它。
现在来看一下精准测试页面,会将它的方法推荐的数据以及在中间添加的断点数据可视化并推送给用户。这样,我们的精准测试触达率已达90%以上。
3)异常检测
除此之外,异常检测是我们测试完成后发现问题的方式。我们会检测异常栈以及变更方法,一旦匹配到问题,就会将异常信息推送给用户。我们将所有的异常信息以及精准的异常信息展示在一个页面上,供用户查看。虽然目前异常检测采纳率仅达到76%,但是我们也不断地在努力,持续优化中。
2.3 实践效果
智能推荐的实践已经持续了两年,经过不断改进,在降低故障率方面取得了持续的成效。人工测试阶段3.8%发布故障率,在自动化平台落地后,已经降低到了1%以下。加之智能推荐平台的实践,我们目前已实现故障率低于千分之4,达到了公司所关注的低故障目标。
三、如何通过本地化提高研发效率?
3.1 整体思路
这部分主要是针对开发人员的需求,开发人员最痛苦的是需要发布到Beta环境才能进行测试用例等操作,自己准备用例也比较繁琐。因此,我们的解决思路是测试左移,将测试过程提前到开发阶段进行,而不是在Beta环境中进行。
另外,开发人员可能不擅长表达,甚至会对QA产生抵触情绪,为了降低沟通成本,我们建立了开发工作流和项目工作台。在平台建设方面,我们期望做本地化测试和开发流水线,尽快收集开发人员的需求,让他们能够尽早完成开发和测试工作。
3.2 本地化平台建设
3.2.1 方案设计
在实践中,我们借鉴了软路由的能力,将Beta环境的配置信息路由到本地,从而实现了本地调试和联调的功能。
3.2.2 IDEA插件开发
基础架构TC同学开发了IDEA同步插件,使得应用可以一键启动,自动拉取测试环境配置并将软路由环境配到本地。此外,本地测试也要将它对应的数据上报到平台,开发对应IDEA组件实现覆盖率数据上报,如下图。
3.3 实践效果
- 本地化方案完成从0到1建设,使用率从0%到达73%,最高时达到80%;
- 自测自发的项目工作量从22%提高到80%以上;
- 项目完成时间从1.9天/个降低到1.2天/个,耗时降低36.8%;
- 通过自动化测试和测试结果推送,减少研发与QA的沟通,提高工作效率。
四、总结与展望
4.1 总结回顾
在本次分享中总共三个部分,总结如下:
- 自动化测试:主要面向测试同学,实现了全自动的回归测试能力,并实现自主运维,无需人工介入,工作繁重的问题得到了解决。
- 低故障能力:面向公司诉求,实现了精准测试与异常检测能力,通过实现发布前测试到异常与线上异常后及时发现能力,大幅度降低发布故障。
- 高效率能力:面向开发同学,通过测试左移到开发侧思路,实现了本地化测试和本地化联调能力,简化了环境准备,数据收集过程,从而提高了开发测试效率。
4.2 未来展望
展望部分是去哪儿网正在做或计划做的工作,包括云端开发、扩展能力、IDEA。云端开发的优势在于性能更高,组件更标准化、更齐全,避免了本地化环境的问题。扩展能力则是希望一种工具能够解决多个问题,例如DIFF能力可以在自动化测试和本地化测试中使用。我们用 IDEA 在不断地开发,使用统一的 IDEA 组件提效开发过程。(全文完)
Q&A
1、测试的用例是不是可以用流量录制回放来做?
2、本地化测试,A-B-C这样调用链路,本地服务如何接替B服务?
3、可以详细说说软路由吗?在本地服务接替环境服务的时候,如何保证请求到的是本地服务?改造网关负载策略吗?注册中心是什么?
4、压测报告一般怎么识别服务瓶颈点,想问下压测结束之后怎么判断当前的瓶颈点是哪个?