魅族自动化测试架构之路

发表于:2016-12-23 14:51

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:王照辉    来源:51Testing软件测试网采编

  团队介绍
  我们团队有一个英文简称:COD。COD有两层含义:戏谑一点说就是Code Of Dog(代码狗),这是我们私下里对自己的戏称;正式一点的话是代表Call Of Duty,大家可能玩过一个游戏叫使命召唤,对于我们来说自动化探索就是我们的使命。
  我们是一个年轻的团队,成员基本上都是在24-26岁这样的年龄区间,主要致力于通过测试技术的研究、开发一系列自动化测试工具和平台,以满足部门的日常使用并提升整个团队的测试效率。
  魅族测试的两个主要框架
  魅族主要使用UIAutomator和Monkey两个框架进行自动化测试,两个框架均为系统原生支持的框架,不需要对系统修改或安装其他应用。
  1. UIAutomator
  UIAutomator是系统原生支持的框架,用它来做系统的稳定性测试是非常方便的,在4.0的机器上,升级完成固件之后就可以直接做测试工作。因为UIAutomator是基于系统底层的,所以整个框架代码不是很多,可以在上面做简单的扩展、实现一些便利于测试工作的逻辑。它还可以支持跨APP的测试,验证APP的功能是否正常、流畅度和待机耗电情况等。
  2. Monkey
  Monkey也是系统原生支持的,我们主要用它来做长时间的压测,如检查7*24小时的压测是否出现崩溃的情况。Monkey可以指定随机事件的种子,通过一些方法调整它的时长,调整事件的比例,来达到测试侧重点的要求。
  3. 两个框架的应用角度
  UIAutomator主要用于回归测试和冒烟测试。对于一些成熟的不容易产生控件变更的项目,我们主要通过UIAutomator的脚本测试APP是否正常;对于一些待机耗电的专项测试,我们也会用UIAutomator的脚本来辅助一些控件操作。
  Monkey主要是用来做稳定性测试和冒烟测试。Monkey属于没有太多逻辑的点击,对于Monkey的冒烟测试,我们主要是测一些安装拆卸能不能正常打开、会不会产生无响应、崩溃等情况。
  魅族自动化测试发展的五个阶段
  第一个阶段
  刚开始涉及自动化的时候,我们有一些专门的人去负责脚本的编码工作,执行是先用USB与设备连接,预置初始条件,比如登陆特定的账户、放一些固定文件到sdcard目录,通过执行结果来收集用例的正确性和某一些失败原因,出现崩溃的话我们会收集它的异常信息,最终生成一份报告,再把这些缺陷信息发布到内部的缺陷平台上去。
  上图显示的是我们在第一阶段遇到的一些问题。最大的问题是报告不是很明确,我们不能从具体的SHELL输出中获取真正的含义,我们也不知道它究竟要达成什么效果?操作步骤是什么?失败了意味着什么?也不能捕获崩溃或是ANR。如果系统某个APP崩溃或发生ANR,单靠UIAutomator框架是拿不到有用的信息的,可能要开一个logcat窗口去收集,而这些信息又不是那么容易可以收集到的。
  测试的过程中,我们希望收集测试结果并对测试的关键操作或步骤进行截图,虽然UIAutomator框架提供了截图,但大家实际编码中的实现方式千差万别没有统一,我们希望用统一的方式收集结果、关键操作和截图,并最终汇总在一起。我们内部有一个报告汇总的过程,但是只靠SHELL窗口的输出很难做到统一无误的汇总,这个过程很困难,需要耗费很多的人力。
  第一阶段面临的主要就是这两个问题,针对这些问题我们也给出了一些解决方案。
  比如对于自动化脚本来说,我们要求自动化脚本必须提供操作步骤和预期的结果信息,这些信息可能就是标记在方法上的注解。我们开发了一个APP,通过收集脚本发出来的广播来收集这个脚本最终的执行结果,刚开始比较简单,就是用例名字加结果,后来添加了操作步骤和期望。我们通过APP对脚本执行全过程的操作步骤进行录制和截图。也通过一些其他的系统底层的组件开发了监控崩溃、ANR和收集运行的Log,统一汇总结果发送给我们的web端展示。
  这是第一阶段整体的架构图。先由自动化脚本提供操作步骤、期望、结果,然后由开发的守护APP提供录制、截图,对崩溃、ANR和LOG的收集,最后到平台上做结果展示,另外还对测试过程中复现的bug与内部缺陷平台对接。有了这个架构后报告就不会像以前那样分散在每个人手里,而是有一个统一的web页面展示,方便了存档与部门间的分享。
  这是我们的报告截图,报告最主要的是以下几列状态信息:某一个模块总共跑多少条、失败多少条、成功多少条、出现了哪些bug等,这些只是一部分信息,还有一些操作比如某一个模块点进去就是显示执行的全部用例和结果信息。
  第一阶段我们整体规划了自动化的报告形式,通过守护APP+WEB的形式实现了人性化的报告输出、错误的监控和与缺陷平台的无缝对接,方便测试人员查看与分享报告并追溯Bug来源。
  第二阶段
  第一阶段完工之后,我们发现脚本方面(主要是自动化脚本)还存在问题。我们会遇到这样一些情况:
  同事A负责某个模块的自动化,但是他今天请假了,他的代码要交给同事B做编译和修改工作,A使用ANT做编译,编码中可能有不规范的路径引用,当这个代码拉到B电脑上的时候就出现编译不过或构建失败的情况。
  或者有一些脚本执行过程中依赖一些资源,比如文档测试,可能需要SD卡放固定的文件,或要求登录特定的账户产生一些操作。而这个脚本跑完之后没有进行有效清理,比如退出账户。这样下一个自动化的登录可能会受到一定影响,如果不退出上一个账户,下一个账户就登录不上,这样就影响了其他自动化,这也导致脚本容错性差。不稳定、自动化执行效果不好等问题(这个可以理解为产出不是特别明显。一个自动化脚本是为了测试目标APP,如果自己本身不稳定,整个测试也是没有多大效益的)。很多同事在写脚本的过程中,对一些登陆账户、删除文件的操作各自实现了一系列的逻辑,这就导致很多地方大家关注的点不一样,没有办法统一,而且不稳定。
  还有一些前置条件依赖手工构造的,如:手工往SD卡下放文件、手动登陆账号,这些前置条件有些并没有实现自动化。还有一个最重要的:它依赖USB的连接。我们都知道,测试过程中,我们需要在shell中敲命令启动UIAutomator测试,而我们有一些不在办公室测试的场景,比如:场测,我们不可能每天搬一台电脑去外部做这样的测试,于是我们希望能够脱离PC执行。
  针对这些情况我们也给出了一些解决方案。
  我们引入了Google出的代码审核工具Gerrit来做测试代码审核,引入Jenkins做Lint扫描和统一编译,把这些平台编译好的包统一发布到web端。我们还将基础操作封装为类库,要求运行时资源打包进行脚本执行文件,然后运行的时候释放。一个脚本执行完成之后,必须对更改的东西做有效清理,比如更改的设置、更改了账户,必须做退出操作,还有用守护APP调用脚本来脱离USB连接。
  第二阶段的整体架构图如上。首先规范整个编译的描述文件,然后打包一些资源,由Gerrit服务器做代码的审核并扫描,再由Jenkins做编译,然后打包上传,最后由守护APP负责拉取这些脚本去调用执行。
  在第二阶段解决了脚本的依赖性、编译、不稳定等问题,主要是通过一些审核、预编译等操作来提高脚本的稳定性。最重要的一点是我们可以脱离USB线缆去执行测试。
  第三阶段
  第三阶段首先要解决的是配置问题,我们内部有不同的机型,有一些机型可以共享代码,但是也有很多是不能共享的,比如:有的机型有NFC 这个设置,而有一些机型没有这个设置,所以代码编写人员要写逻辑判断来排除某些用例。不同机型执行的时候脚本执行参数可能不一样。比如早期我们需要根据机型对一些用例做一些特殊处理,通过脚本传递一些参数进去,让它做一些特殊的筛选工作。我们有一些基于Flyme的固件,也有一些基于YUNOS的固件,不同的固件会有一些UI上的差异,所以可能同一个应用我们却要用不同的脚本去适配不同的固件和机型。
  早期的做法是依赖脚本编写人员在代码里做大量的IF、ELSE判断,判断特定的设置是否存在。但是这样的配置对我们来说很繁琐,比如今天突然来一个新机型做自动化测试,需要很多人修改代码,加上这个机型的判断、给它制造一个新的场景,这些都是很耗费时间的工作。
  针对这个问题我们也有一些解决方案。
  从设计模式的角度来说,有一个办法是把变化的部分抽离出来做封装,我们通过提供模块配置做这样的抽离工作。首先我们引入一个模块的概念,这个模块就是对应APP的脚本测试集,模块里包含针对不同场景(固件、机型等)的用例。我们又引入“仓库”的概念对应一个模块集,这个仓库是不同的脚本集,比如Flyme4、Flyme5或者一些特定场景测试。
  这是我们第三阶段的仓库图。主要是脚本用例划分的结构,某一些用例差距比较大就单独拉出来做新的用例。
  这个界面主要是我们内部用例配置界面。在我们内部有一些不同的用例,一些用例适配Flyme一些适配YunOS,针对不同的用例和机型我们可以通过调整“适配机型”和“用例选择”这两个参数来抽离配置,比如机型A的Flyme版可以执行全部用例而YUNOS版只能执行其中第10到第15条用例,就可以通过用例选择解决这样的问题。最终配置完成后界面会根据配置生成一串带有参数的命令。
  下面还有两个需要SD卡和SIM卡的参数,主要是解决测试过程中有一些自动化测试的依赖场景问题,比如文档需要SD卡存在、短信电话需要保证SIM卡存在。这两个参数主要的作用是执行过程中约束这样的条件,比如达不到的时候会给出弹框或提示。
  第三阶段主要通过一些模块的配置来解决不同机型和版本之间的依赖问题,通过参数扩展脚本的适用性。在这个阶段之后,我们不需要在脚本做逻辑判断来适应机型。有了新机型我们可以在刚才的页面配置上勾选几条用例,然后确定就可以了。
  第四阶段
  第四阶段主要是要解决自动化的“自动”问题。前几个阶段完成后报告收集没有太大问题,但是内部执行的时候,经常一天有很多设备或固件做自动化测试,而每个人手上的设备有限,A可能只有MX5、B只有MX6,脚本执行的时间有长有短,某一个设备跑完了就闲置浪费,我们也不好协调这种资源的分配。
  此外,升级固件也需要手工来处理,测试一个固件时我们需要手动拷贝固件到设备然后操作设备进行固件升级,这也会浪费很多时间。有时候有些人可能做很多机型的自动化测试,就需要拉这些固件一个个去升级、测试,这样很繁琐很浪费时间。
  我们的守护APP执行过程中主要的操作是:选择某一个模块点击执行操作,这个阶段的执行也是手动的。
  另外,我们失败的用例需要人工确认,这个情况相信大家都遇到过。比如一部分用例失败了,可能是因为初始条件没有达到或是UI卡顿而导致的,如果能重复执行这些用例很大程度上会减少这种场景下的失败数量,早先这个重复的操作是由我们人工完成的,我们希望能以自动的形式帮我们完成这部分工作,让失败的用例重新再跑一遍。
  针对这些问题的解决方案,就是比较抽象地提出了“设备池”的概念,把这些设备集中在一起,统一供电、统一管理,在每一个设备上装上我们添加了推送功能的APP,进行任务分发和固件升级工作。Web端从一个单纯的报告展示页面改造为任务中心,不单单只是展示报告,也可以创建任务,管理任务、查看任务状态等。我们把客户端和WEB端通过Push连接起来,基本得到完全自动化的调度平台。对一些执行错误的用例我们尝试通过平台重新分发,很大程度上避免了因UI控件找不到而引起的用例失败。
  第四阶段我们整个平台的架构主要分为两部分:客户端和服务端。客户端有一部分本地调度的逻辑,因为它需要一些脱离平台执行的场景,比如场外的测试,它可能没办法连接到内部的平台。客户端还包含一些系统组件,如录制屏幕、崩溃监测、LOG收集、以及通讯的组件。
  在这个阶段我们也对UIAutomator和Monkey做了一些改造。比如前一个阶段有一个用例选择的配置项,即选择部分用例执行,这个功能可以通过调整UIAutomator执行参数实现,但我们觉得这可能不是很合理,在改造的过程中我们专门为这一系列脚本和工具端的通讯需求提供了AIDL接口,我们内部把这个负责UIAutomator和工具通讯的组件叫UIBridge。在平台方面按功能主要分成在线列表、任务管理、模块管理和报告展示等。
  第四阶段我们实现了完全无人工干预的自动化。实现了这点就有了上下衔接的可能,比如编译出来固件,可以通过持续集成全自动的进行固件的稳定测试、回归性验证等工作。同时也实现了资源的有效整合,以前做手工测试的时候,10个模块准备5台设备,需要一个下午的时间做整体测试,而现在有了自动调度逻辑,可能只需要两个小时就足够了。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号