持续交付探索与实践(二):自动化工具链建设

一、前言

上一篇介绍了我们是如何通过建立灵活、紧密的交付流水线来解决各业务线交付过程中的不顺畅及信息不透明等问题的。如果说流水线的引入带来了汽车生产效率的第一轮革命性提升,那么汽车生产效率的第二轮革命性提升则是由生产线的机械化升级所带来的。类似的,在有了良好的研发过程流程化支撑之后,我们也需要将流程中的各类事务和活动尽可能的自动化,以便解放人的双手,提升研发过程效率。下面我将主要从测试自动化、通知自动化、配置自动化这3个方面概要的介绍下我们在自动化这一块的实践。

自动化工具链建设

二、测试自动化(解放双手,测试提效)

2.1、自动化框架搭建

通常来讲,自动化测试可以分为单元测试、接口测试、UI测试这三个层面。下层测试用例的成本(包含代码维护成本、测试准备成本和执行时间成本)会低于上层测试用例,如下图所示:

自动化分层

越往上越靠近业务和最终用户,但与此同时,执行起来成本也越高、速度也越慢、投入产出比也越低。因此行业内最佳实践往往是加大底层单元测试的占比,再配合一定的接口自动化及UI自动化加以补充,单元、接口、UI自动化测试的占比整体约为7:2:1,我们总体上来说也遵循了这样的实践,下面简要介绍下每一层我们的实现方案。

UI层

UI自动化框架初期我们选用的是Uiautomator2,其底层基于Google Uiautomator,提供了一系列便利的 python 接口,相比Appnium等工具会更加轻量级,稳定性和可拓展性也更佳,其工作原理如下:

Uiautomator自动化

python端:运行脚本,往移动端发送HTTP请求

移动设备:安装atx-agent,启动Uiautomator2服务进行监听,解析收到的HTTP请求,转换为Uiautomator2的代码进行操作。

使用Uiautomator2可以很便捷的编写python脚本来实现app的自动化用例,我们用这种方式实现了大部分的用例。但对于一些流程较复杂、变化相对频繁的业务功能来说存在问题,比如:

  • 因业务需要增加了新的告警/提醒弹窗,而我们没有事先获知并在用例中进行相应的处理,就会导致用例执行中断;
  • 某一些页面做了调整,虽然对应的按钮仍然在界面上,但是原先的定位方式已经失效。

为了解决上述问题,我们引入了Espresso,它是google官方提供的UI自动化框架,相比Uiautomator2,它可以和被测项目的代码有一定的交互,可以直接调用被测项目中封装好的函数来实现更多的拓展,我们主要用其来覆盖一些需要有复杂交互的用例,以便保障用例的稳定性。针对上面提到的问题,相关的解决代码如下:

espresso自动化 espresso自动化

而对于一些游戏业务,普通的页面元素校验方式不能很好的满足,所以我们又引入了Airtest增加了对应的图像识别的能力。这样,最终形成了目前的这套Espresso+Uiautomator2+Airtest的开源UI自动化解决方案。

接口层

接口测试我们选用的是robotframework框架,它有着非常丰富的库,同时也方便自定义library进行拓展,我们在原有基础上增加了HTTP Library、NSQ Library、MC Library、Redis library、Database library等扩展库支持了业务所需的各类操作和校验;同时将用例体及相关配置进行了分离,实现了数据驱动,提升了用例的可重用性和可维护性,其整体架构如下:

robotframework架构图

除了针对后端接口本身的测试,APP客户端对后端接口的容错也是很重要的一个点,若客户端对后端接口未做好容错处理,则很可能由于后端接口的返回异常、或者后端接口改动未能知会客户端导致业务异常甚至是APP崩溃的情况,我们通过整合自动化平台及YAPI接口管理平台实现了接口容错性校验的自动化,整体方案如下:

app容错性测试自动化

1、app测试包实现支持指定接口的特定开关,开关打开后对应的接口请求转而指向YAPI平台的mock server

2、YAPI平台的mock server会事先根据接口协议自动批量生成mock规则,每次收到请求时从mock规则池中轮询并返回

3、自动化平台执行对应的APP UI自动化用例,到特定步骤时打开开关,使得对应接口的response从mock规则中获取

以上方案相比业界普遍采用的结合monkey的方案有以下2个优点:

  • 用例调度和执行可以通过自动化平台进行更灵活的控制,比如针对某个版本改动内容涉及的接口进行重点验证,能在短时间内尽可能的覆盖更多的场景;
  • 接口相关信息管理统一化和配置更新及时化。由于整个部门的接口信息的管理配置本身就采用了YAPI平台,所以当有相关接口改动时就能第一时间得知,且通过Mock server可以很方便的定制和修改各类mock规则。

当然,该方案也有对应的缺点,就是需要有一定的用例维护工作量。

单元层

单元层我们选用的是junit框架,由各项目的研测同学共同维护,同时我们也会结合jacoco进行覆盖率的检测,最终的测试数据及报告会直接在持续交付平台上展示。相关技术方案与细节与业界的实践无太大差异,这里就不再赘述。

 

2.2 自动化实施策略

在实现了上述自动化测试的能力之后,需要更合理更聪明的利用好这些自动化能力,以便最大化的发挥其价值,同时又尽可能的达到质量与效率之间的平衡。下面介绍一下我们在自动化执行策略优化和落地推动等方面所做的一些改进:

1)统一执行脚本

原先各项目执行脚本均相对简单,我们执行的方式是直接将对应的单元用例执行命令体现在对应的junit job中,但是随着业务的发展,单元用例的增多,各组各项目都出现了更多定制化的要求。比如有些项目的部分用例还不稳定,只希望跑特定模块的用例;有些项目需要特定的clean或build参数,这就导致了我们测开团队出现了大量的配置和维护成本。

所以我们我们制定了统一规范,要求大家把各服务对应的单元执行脚本统一写在命名为cirun.sh的脚本中并存放在项目仓库的根目录;通过这种方式就实现了用例调用脚本和具体执行命令的分层,将执行脚本的维护工具下发给了具体的业务团队。对于持续交付平台来说,不管具体的单元用例执行命令和执行参数如何,只需要统一执行cirun.sh脚本即可;而对于各业务方来说,执行,单元用例的执行范围、参数发生变化时,自行修改自己项目仓库下对应的cirun.sh脚本即可,不用担心配置出错而导致其他项目也无法正常执行,同时也方便对构建脚本进行版本控制。

2)紧跟新功能开发进度

保持测试用例与新功能开发同步更新,可以给新功能提供及时的质量反馈。因为如果只是不断滞后性的补充用例,那么自动化测试的覆盖可能一直落后于功能开发,无法起到全面的质量保护网的作用,大大降低了自动化的价值。

我们在这方面的实践方案是设定自动化用例覆盖率检查点,我们基于jacoco进行二次开发实现了细化到类和方法粒度的代码覆盖率检测,同时通过在研发流程中设置对应的检查点,判断当前特性分支覆盖率如果低于主干分支的覆盖率时,则进行阻断,以此来保证用例更新与新功能开发的同步。

单元测试覆盖率检测

3)坚持质量重于数量

自动化用例质量低下会导致用例结果的不可信,而且这种用例本身的质量问题所导致的失败会大大增加我们的无效投入,也会令大家慢慢失去对自动化的信心,甚至可能出现破窗效应,逐渐对失败的自动化用例视而不见。所以,我们对所有的自动化构建都设置了通过率100%的质量阀,未达到则无法进入下一步流程。同时,我们也会有相应的工具去定期检测每个服务的无效用例,以此来保障用例的整体质量。

单元测试通过率检测

额外提一下,这里并不是说用例的数量完全不重要,我们对覆盖率也是有一定要求的,只是说我们没有对每个团队定义一个硬性的、统一的覆盖率目标。我们这边的操作方式是由质量团队和研发团队一起,根据不同的业务特性来确定每个项目都有哪些是核心模块,然后把这一部分模块的覆盖率做到极致,也就是达到100%的覆盖率。

4)提升自动化执行次数

这里并不是指在同一场景下重复执行多次测试用例,而是指在多个不同的场景中重复利用这些自动化用例。比如开发人员在push代码后、在合入到集成分支后均执行对应用例,而不仅仅只是在正式提测前才执行一次用例。以便在不影响主流程效率的前提下,将自动化用例的价值最大化。

提升自动化执行次数

5)充分利用夜间时间和资源

我们的实践方案是:自动检测当天有代码变更的所有项目和分支,并在夜间闲时进行全量构建,并通过邮件的方式将结果发送出来,使得开发人员第二天早上一上班就能收到针对前一天工作的整体质量报告,以便于及时跟进相关问题并进行修复,避免问题不断堆积延后,导致修复成本的增加;同时我们也会对所有项目master分支的用例(稳定用例)进行定期构建,以便尽早发现一些不稳定因素,提升用例的整体质量。

夜间自动化测试

6)让开发成为第一用户

即尽可能的将对应的自动化测试前置到研发环节中去执行,将其作为研发自测的手段之一,而不是仅仅作为测试人员用来验收开发人员工作质量的工具。

三、通知自动化(一旦完成,立即反馈)

有些时候,虽然我们在各个研发环节内部做了足够多的优化,但是跨环节的协作可能还是存在大量的流转与沟通成本,从而导致组织之间的谷仓困局,如下图所示:

组织间的谷仓困局

为此,我们建立了相应的自动化通知机制。同时,结合通知内容或载体上的交互确认来实现接收到通知后的确认和反馈,从而真正的实现“一旦完成,立即反馈”。目前我们的自动通知从通知方式上主要分为2类:

3.1  邮件通知

邮件通知一般用于涉及大量信息并且需要留档的通知。比如发版前的验收通知,我们通过在邮件中展示app包二维码,能让产品、测试等同学很方便的下载APP进行最终的验收体验;通过需求列表及测试结果、遗留问题等信息的聚合展示又能直观的看到有哪些需求进入了版本以及整体的质量风险如何。

邮件自动化通知

3.2  企业微信机器人通知

这种一般应用于需要被通知人及时响应的通知:比如需求提测需要介入、构建失败需要跟进处理等等;通过将关键信息汇总展示能让被通知人第一时间了解需要跟进事项的详情,通过一些交互链接又能让大家很方便的跳转到对应系统上进行相应的操作。

企业微信机器人

四、配置自动化(降低成本,减少出错)

除了前面提到的流程流转之外,整个交付过程中也涉及到不少的配置动作会耗费一定的精力且容易出错,比如代码审核的配置,发布项目的配置等。为了减少用户的配置成本,我们在配置自动化方面也做了不少改进,下面我拿2个案例介绍下我们在这方面的实践。

4.1  代码审查标签双向同步

目前我们的持续交付平台在研发阶段和测试阶段都有设定相应的code review确认节点(分别对应代码初审和代码终审),需要对应的审核人确认完成代码审核之后才能流转到下一步。但是实际操作过程中存在一个问题:就是持续交付平台虽然设定了相应的确认点,但是没法进行审核过程的支撑,这就导致审核人员要先去gitlab上进行代码审核,然后再回到持续交付平台进行确认动作,比较不便。

为了解决这个问题,我们结合gitlab api和webhook实现了代码审核标签的双向同步:当审核人在gitlab对应的merge request打上审核通过的标签后,webhook会监听到对应动作并同步状态给持续交付平台。 反过来,如果审核人员在持续交付平台上进行审核通过的操作,系统也会调用gitlab api在对应的merge request上打上相应的标签。这样,在不改变用户操作习惯的前提下,满足了交付流程中的代码审核规范要求。

gitlab webhook标签同步

4.2  智能化发布配置中心

另一个案例是关于发布项目配置的。我们整个研发过程中会涉及到多次的部署行为,比如测试环境的部署、集成环境的部署、线上机器的发布等等,不同的环境涉及到不同的机器集群和不同的发布配置;而且,当环境有所变动时,对应的配置也需要进行调整。而这些配置信息的确认过程是极为枯燥和繁琐的。为了解决这个痛点,我们主要做了2点改进:

1)首先是配置信息的智能填充:比如我们通过打通内部的RMS发布平台,自动获取最近一次的发布配置参数进行预填充;并且根据代码变更情况,在发布选项中优先展示可能要发布的项目,使得开发人员每次发布时无需从0开始将全部参数配置一遍,仅需核对自动推荐的配置信息并根据实际情况进行少量调整即可;

2)其次是可视化配置中心的建立:我们通过将各个环节的配置信息进行聚合展示,并对异常配置做显性化的提示,能让大家很直观的看到整体的配置情况以及所存在的问题。

通过以上措施,将各类配置化繁为简降低人工成本同时,也尽可能的避免了因为配置出错而导致的过程损耗。

发布配置中心

五、结语

以上就是我们在自动化方面的所作的一些探索和实践。由于篇幅的关系,本次主要是对整体实践方案进行介绍,没有对其中的一些细节进行过多的展开,后续有机会的话再进行针对性的介绍。

下一篇: 持续交付探索与实践(三):指标度量体系搭建

 

posted @ 2022-01-24 10:35  Tony-g  阅读(683)  评论(0编辑  收藏  举报