自动化持续集成已经是老生常谈的问题了,相信大家都不陌生,不管大厂小厂基本都有自己的一套架构和流程,我们对它有着美好的期待,理想中的它是这样的。
它能够带来测试效率的提升,减少大量重复的工作。 它能够高频的执行自动化,帮助我们快速发现并修复缺陷 它能够给我们带来信心,让我们自信的发布。
但是,我们在建设落地和业务发展的过程中,遇到各种各样的问题,导致实际结果和目标有所偏离。
随着业务复杂度的提升和发展,自动化运行速度越来越慢,资源不足导致的排队时间越来越长,使得每次发布迟迟得不到结果,拖慢发布节奏。
自动化稳定性不足,脚本问题、平台问题、环境问题等让大家对自动化结果逐渐变的不信任,出现失败case复现不了,无从排查,选择无视。
进而对CI卡点不再重视,为了不被卡点,不断降低自动化通过率、覆盖率等阈值。
过于追求自动化指标,导致做了很多负EV的投入,得不偿失。
久而久之,CI卡点变得形同虚设,导致大家进入了写了很多自动化用例,每天也都再跑,但是却发现不了问题,线上故障还是层出不穷的困境。
二、解决思路
为了让自动化持续集成发挥真正的价值,让测试人员减负提效,真正提升线上质量,我们结合现有痛点和业务同学实际诉求,在自动化CI流程、基础设施、平台能力等方面做了一系列的改进提升。
目标是在保证自动化持续集成本身运行稳定的情况下,提升运行效率,CI卡点有效性,降低自动化结果排查成本,再以指标度量推动进一步提升,形成良性循环。
2.1 现有架构介绍
首先介绍下我们自动化持续集成的大致架构,便于理解后续的一些落地实践措施。下图中pub和moon是酷家乐内部的devops平台,分别负责前后端的持续集成、构建和发布。
我们持续集成需要运行种类有很多,包括接口自动化、UI自动化、单元测试、变异测试、静态扫描等等,它们都通过jenkins进行统一调度,大部分jenkins slave节点都基于k8s进行管理,本文重点介绍接口自动化和UI自动化的治理改进。
三、落地过程
接下来从运行效率、自动化稳定性、CI流程、指标度量几个方面逐一介绍我们具体做的事情。
3.1 运行效率提升
代码变更、服务部署、定时任务等都会触发各种自动化运行,这个时候运行效率就尤为重要,耗时过长会导致整个CI流程阻塞,在各类自动化任务中,运行时长UI自动化>接口自动化>单元测试,我们对自动化任务运行时长的要求为不超过半小时。
我们首先对UI自动化进行了治理,UI自动化刚开始都运行在windows机器上,由于机器资源有限,任务平均排队耗时在半小时左右,且每个任务运行时长也都基本超过一小时,这样一个任务从触发到运行完成往往需要一个多小时,是不可接受的。
首先要解决的就是机器资源问题,酷家乐前端页面渲染非常依赖GPU资源,基于公司原有的k8s架构和管理运维考虑,我们最终选择了带独立显卡的linux物理机,这样便于后续管理和维护。自动化运行模式也从有头带界面模式改为headless,有助于进一步提升运行效率。经过不断地尝试和资源调整,单pod GPU最终的资源配置为(tencent.com/vcuda-core: "8" 、tencent.com/vcuda-memory: "3"),两台linux物理机最大可以支持96个任务并发。
基于linux运行后,任务并发数量已经不再是瓶颈,为了充分利用资源,我们支持了以文件维度并发运行自动化的能力,大大缩短了运行耗时。
把UI自动化迁移到linux上运行,整个过程持续了小半年,目前大部分自动化用例都平稳运行,其中有小部分因为渲染效果、字体等原因还需要在windows机器运行,这部分我们通过用例打标的方式来做识别,通过并发运行的机制,让同一个测试计划里部分用例运行在linux机器,部分用例运行在windows机器。
最终的效果可以看下面表格:
3.1.2 接口自动化
接口自动化运行时需要去实时构建对应的测试环境,然后再运行响应的自动化用例,其中构建+部署往往耗时较长。为了减少不必要的构建,对于相同的分支和commit,会直接去获取历史构建,减少耗时,这个策略能覆盖70%左右的自动化任务。
我们平台接口自动化任务是多线程并发运行的,但是当并发量太高的时候会对服务产生性能压力,导致很多预期外的超时失败。改成单线程可以避免这种问题,但运行效率又达不到预期。
通过线程池拆分,我们把原先的单个线程池改为多线程池,每个线程池同一时间运行一个任务,线程池内的线程支持扩缩容,通过控制线程池线程数量,找到了效率和正确性的平衡点。
| 优点:
缺点:
| |
| 优点:
缺点:
|
3.2 自动化CI流程优化
自动化持续集成贯穿了我们整个研发测试的流程,根据需要在不同环节运行相应的自动化,随着自动化平台能力的提升和用例的逐渐稳定,我们把自动化做了更多左移和右移的尝试,并引入了流量回放、日志巡检等新的能力,以发挥更大的价值。
3.2.1 自动化左移流程
在接口自动化和UI自动化运行逐渐稳定之后,我们进行了左移的尝试。刚开始设想的比较理想,希望能直接在mr阶段运行接口和UI自动化,遇到了比较多的问题,比如:
基于上述问题,我们从现有的测试流程入手,找到了一个比较合适的切入点:提测环节。提测动作是开发推动issue到待测试的环节,测试对待测试issue进行冒烟测试验证主要功能正常运行,这个时候测试介入check自动化左移结果也比较合适。
当测试发现有自动化运行失败bug或者自动化任务通过率未达到100%时,进行人工确认并指派bug给对应开发。
为了让自动化左移尽可能的减少人工介入,让流程更加丝滑,我们对于自动化环境构建、自动化用例筛选、结果通知等都做了功能优化。
3.2.2 自动化建issue
各种类型的自动化运行完成后,结果以两种形式呈现:系统自动创建的issue或各平台上待确认的事项。
刚开始我们都统一创建自动化issue,通过issue呈现自动化运行失败的结果,通过issue去收口。但是受各种因素干扰,比如上下游影响、数据问题、用例本身稳定性问题等,再加上issue处理本身流程较长,对一些同学日常造成了一些干扰。对此,我们做了两件事:1、引入自动化结果确认分析的流程,分析有问题后再人工进行issue创建关联 2、对自动化运行结果进行降噪、智能分析,然后再创建issue,提升issue有效性(降噪和智能分析在下面稳定性治理中会有介绍)。
因为不同敏捷组习惯不同,有些组习惯通过issue来进行问题排查,有些组则希望通过事项进行确认,所以两种模式都保留并行。有时候并不是一套流程就能适应所有团队,也没有完美的了流程,需要结合团队实际情况考虑,适当变通。
3.2.3 结果通知事后追溯
自动化运行结果会应用在部署发布的卡点上,临近发布才去处理卡点会阻塞发布,因此除了各节点的卡点通知外,我们每天早上都会统一进行结果推送并提供相关大盘,让一线同学进一步感知,提前介入进行处理。
目前通知大盘有个人、团队维度,每日、每周维度,管理者视角维度,让各角色关注自己想要关注的数据。
个人每日看板 | ||
团队每日看板 | ||
管理者视角的自动化dashboard |
| |
每周运行结果汇总 |
|
3.3 自动化稳定性治理
3.3.1 运行结果稳定性
为了提升自动化运行结果稳定性和创建的自动化issue有效性,我们对结果做了降噪和智能分析。
结果降噪是在多次失败重试后,对于还是失败的case会去基线环境stable(代码和线上保持一致)运行并拿到结果和测试环境运行的结果进行比对,如果两次结果一致,则认为是噪音不创建issue,否则认为是bug。
在进行结果降噪处理后,还会进一步进行结果智能分析,这里有通用规则和一些业务相关的规则,只要命中了规则依旧不会创建issue。这里列举几个规则:
经过这几步处理后,大概50%左右的失败用例可以被过滤掉,不会对一线同学产生干扰。
对于经过处理后还是失败的情况,我们专门建立了失败用例看板,以用例失败次数维度进行度量,每周针对失败次数高于一定频次的用例专项治理。
3.3.2 自动化结果排查能力
古希腊哲学家赫拉克利特说过:”人不能两次踏进同一条河流“,自动化运行时的服务状态和环境状态也是如此,有时事后排查想要完全模拟当时一样的情况是一件比较困难的事情。
比如服务本身缓存问题导致不同时机运行的代码路径不一样,依赖环境的网络抖动、上下游问题、中间件问题等,要完全模拟成本很高。
对于接口,在用例运行失败时,记录当时依赖服务的快照信息,包括相关警告、服务存活状态、异常日志等,被测服务在运行该用例的代码覆盖情况也会进行记录,这样可以最大程度的帮助排查不可复现的用例失败情况。
记录单个用例请求的代码覆盖情况,我们是在用例运行失败后,起另外一个单线程去执行该用例,在用例执行前先reset被测服务的覆盖率,然后再触发用例执行,执行完成后dump生成jacoco.exe文件。
3.3.3 jenkins稳定性治理
jenkins是我们自动化持续集成调度的关键核心,稳定性至关重要。当每天自动化运行数量少的时候还比较稳定,随着自动化运行数量日渐增多(日均1W+),就遇到了各种各样的问题,比如fullgc、磁盘容量问题、网络带宽问题等等。
这里例举几个优化点
控制构建历史保留的数量,jenkins的构建历史记录会加载到内存当中,当保留的构建记录太多会导致频繁的fullgc。 但是为了能支持查看近30天构建日志和自动化结果(强需求),同时不产生磁盘容量问题,我们把相关的日志和结果都上传到了cos,需要查看的时候实时下载 还有,千万不要轻易安装插件。
3.4 指标度量
做了这么多事情,我们希望能有合适合理的指标来度量和进一步推动提升自动化回归能力,让自动化真正发挥作用。我们对指标做了分级,设立了三级指标。
一级指标,即结果指标。起到 “后视镜” 的作用,有一定的延迟性 二级指标,即拆解指标/改善指标。对结果形成进行构成拆解或者直接可以作用以改善结果 三级指标,即改善指标。可以对应到一个或一组改进行为以获取对结果的部分改善。
其中一级指标有两个,一个是正向的结果指标,自动化故障发现率,自动化发现率越高,则我们的自动化回归水平就越高。一个是负向的结果指标,自动化故障遗漏率,通过反向推导,自动化遗漏越多,自我们需要补充的自动化要求越多。
然后对这两个指标进行拆解,打得到二级、三级指标,最终形成我们的自动化度量大盘,下面列几个二级指标:
指标价值 | ||
自动化的覆盖率越高,我们自动化回归越能拦截问题 | ||
自动化卡点如果运行起来,能有效拦截各类潜在的线上故障 | ||
自动化越覆盖大客户以及故障等级定义,约能拦截各种重大遗漏故障 | ||
自动化异常未处理率 | 降低自动化发现后未处理的个数,可以有效的提升自动化发现问题遗漏到线上 | |
关键用例自动化遗漏数 | 自动化场景遗漏越低,我们对于大客户的保障能力越强以及故障遗漏率越低 |
经过各项能力、流程和指标的建设,在部门目标明确的前提下,目前我们的自动化故障发现率已经顺利达成既定目标。同时,各项关键卡点阈值的符合率几乎达到了100%,也只有在这些阈值完全达到标准时,我们的自动化持续集成卡点才能真正发挥其应有的作用。
我们的自动化持续集成工作初步实现了快、稳、准的目标,具体表现为:
整体运行时间提升了50%,显著优化了运行效率 由于各类原因导致的自动化任务失败率已从17%大幅降低至2%,展现出更加可靠的执行效果 自动化issue有效率由原来的40%提升至70%,极大提高了问题处理的效率和准确性。
展望未来,我们将进一步整合公司内部各类回归测试平台与自动化平台,力求将其纳入到自动化持续集成之中。同时,我们也计划通过低成本手段进行左移和右移,促进开发团队更多地参与到这一过程中,共同推动质量提升。
此外,将AI与自动化能力相结合也是我们接下来探索的重要方向。例如,我们可以基于现有用例来辅助生成不完整用例场景;进一步实现对自动化运行结果进行智能分析与自动修复;并且针对性地指导提升代码覆盖率等。这些努力都旨在提升整体测试效率与软件质量,使得我们的质量效能体系更加完善和高效。
微信扫一扫
关注该公众号