UI自动化Macaca-Java版实践心得

简介: #### 导语 在上篇分享中,跟大家分享了[Macaca-Java版入门指南](http://www.atatech.org/articles/61699?commentId=103931&msgid=965698#comment-103931),相信很多同学已经可以依据教程开始实践UI自动化

导语

在上篇分享中,跟大家分享了Macaca-Java版入门指南,相信很多同学已经可以依据教程开始实践UI自动化工作,但入门问题解决了,要真正在业务中实践还需要面临不少挑战,这篇文章则紧接上一篇,就Macaca在业务中的实际应用给出一些经验总结,希望能给在迷茫中不知如何入手的同学们一些方向,同时欢迎大家就本篇文章中涉及的一些方案给出更优的答案,大家一起进步。

当Macaca遭遇具体业务

1. UI控件不同平台的统一处理问题

首先,我们看一下对于单个平台,是如何做控件的查找与操作的:

    //SampleTest.java
    
    public void test() throws Exception {
        driver.elementById("targetElementId"); // elment的唯一标识
        driver.click();
    }

当平台扩展为多个时,一般来讲,如何进行同一个控件的操作呢?比如对应同一个按钮,在iOS平台,我们可以知道他的name属性,但是在安卓平台,对应的同一个控件,没有name属性,需要通过id属性来获取,那代码就会演变成如下样式:

    //SampleTest.java
    public void test() throws Exception {
        if (driver.curPlatform==PlatformType.IOS)
        {
            // 如果是iOS平台,根据name属性查找控件
            driver.elementByName("targetElementName");
            driver.click();
        } else {
            // 如果是安卓平台,根据id属性查找控件
            driver.elementById("targetElementId");
            driver.click();
        }
    }

众所周知,对于UI自动化,控件的查找是使用相当频繁的一种操作,那么问题来了,有没有一种方式,可以统一控件的查找而不必通过一个接一个的if else分支来完成呢?

2. 测试稳定性问题

测试的稳定性,是影响自动化测试的另一大因素,因为移动端操作场景的复杂性,测试用例执行的过程中可能出现多种意料之外的响应,比如点击某一个按钮,预期结果是进入下一个页面,但是却弹出了某个弹框,或者真正跳转的页面并不是我们所预期的页面,或者跳转了我们所预期的页面,但因为网络数据的加载主视图并没有刷新,这样一来,针对我们的目标页面所做的操作都会失败,因为我们无法找到预期页面的目标控件,在这种情况下,我们需要在保证预期页面已经加载的情况下再执行预期流程的用例,如何做到这一点呢?

再者,长距离到达组件入口的问题也是影响自动化稳定性的另一因素,比如我们想要测试某个基金详情页,但是要进入某个详情页,必须经过登录-首页-A页面-B页面-目标页面几个必须步骤,在到达目标页面之前的任何一个链条中出现中断,这次测试就等于无效了,这种问题怎么破?

当然,影响自动化测试稳定性的场景还有很多,这些在真正的业务实践中会逐步暴露出来,如何保证自动化测试的稳定性,是自动化测试的又一个难题。

3. 测试报告输出问题

对应每一项测试流程,执行完毕之后我们都希望能看到详尽的测试报告,如何快速高效的输出可读性强的测试报告,同样是一个必须解决的问题。

4. 学习维护成本问题

自动化平台或者工具如果对环境配置、使用规范,脚本等有较复杂要求的话,那么对于入门刚刚的测试工程师来说有一定的学习成本。另外,跟随目标产品的版本迭代,自动化脚本要做对应的调整,如果对应的调整成本比较高,也很难保证将自动化的工作方式坚持下去。

我们是如何解决这些问题的

1. 如何解决不同平台的控件统一问题

研究上面的第一个问题,我们会发现控件的获取虽然根据平台不同而需要单独处理,但是控件的获取方式其实都是统一的,获取控件有两大要素,一是获取控件的方式,比如name,id,xpath,css,class name等等,二是要获取控件的值,这个值是与获取控件的方式想对应的,针对移动端测试来说,目前一般覆盖iOS,Android两个平台,我们以这个为例,其实对于UI操作上的一个控件,提供两个平台分别的获取方式以及值就可以解决控件一致性的问题,代码如下:

    // CommonUIBean.java
    
    /**
     * 当安卓 ios两个平台对应同一控件的获取方式不一致时使用本构造函数
     * @param androidBy 获取安卓对应控件的方式
     * @param androidValue 获取安卓对应控件的值
     * @param iosBy 获取ios对应控件的方式
     * @param iosValue 获取ios对应控件的值
     */
    public CommonUIBean(GetElementWay androidBy,String androidValue,GetElementWay iosBy,String iosValue){
        this.androidBy = androidBy;
        this.androidValue = androidValue;
        this.iosBy = iosBy;
        this.iosValue = iosValue;
    }
    
    /**
     * 构造函数,用于ios&android两个平台获取UI一致的情况
     * @param commonBy 统一获取控件方式
     * @param commonValue 统一获取控件值
     */
    public CommonUIBean(GetElementWay commonBy,String commonValue){
        this.androidBy = commonBy;
        this.androidValue = commonValue;
        this.iosBy = commonBy;
        this.iosValue = commonValue;
    }

如上图这样,我们就统一了控件的一次性获取问题,通过这一层封装,如果要表示跨两个平台的一个控件,就可以简化为如下这样:

    CommonUIBean targetElement = new CommonUIBean(GetElementWay.ID,"targetElementId",GetElementWay.NAME,"targetElementName");

2. 如何保证测试稳定性

1、对于要测试的页面抽象成类,增加页面是否加载成功的逻辑,所有页面内部的测试逻辑,均在确认该页面加载成功后再执行从而保证自动化稳定性。

2.对于长距离到达组件入口的问题,通过scheme跳转解决。具体来讲,对于目标页面,只要支持scheme跳转,我们可以直接通过scheme的方式从首页直接进行加载,这样可以一步到达目标页面,省略掉了前面的诸多链路,从而保证了测试的稳定性。当然,这种方式需要依赖开发同学的支持,只有在开发层面上尽可能多的支持独立页面的scheme跳转方式,才能真正使这个解决方案大放光彩。

当然,除了这些之外,对于其他分支的阻塞场景,一方面需要我们对业务复杂度的深入了解,一方面需要在今后的实践中不断积累。

3. 如何详尽的输出测试报告

对于这个问题,我们是分这么几步走的:

1.按照业务需求将错误类型进行分类整理

2.规范化结果输出的规则

3.在对应节点按照既定规则输出日志并写入文件

这样,用例执行结束后,我们就可以看到具体的执行过程以及结果了,规范化日志输出的规则还有一个好处是便于今后结果的集成展示,比如我们要通过web直观的看到执行进度以及结果的时候,就可以通过解析日志得到相应数据。

4. 学习维护成本问题

关于学习成本,就要回到我们的标题,我们这里讲的是Macaca-Java版最佳实践,其实在最早的调研阶段,我们都是通过Javascript写用例的,但是考虑到大部分同学的学习成本,所以在Macaca支持Java后,我们立即转型到Java版本上来,这样大大减小了学习成本,另外,我们在设计自己的框架的时候,设置了config配置文件来配置通用信息,比如应用信息、用户信息等都可以通过配置文件配置,对于用例编写中常用的类进行了封装,形成了一套用例编写规范,这些对于新上手的同学都降低了接入成本,甚至对于不熟悉Java的同学,都可以比较easy的比葫芦画瓢的编写自己的用例。

关于维护成本,我们对于控件的封装使控件更新的成本变低,对于Page的封装,使得同一个页面的测试入口都集中在一起,每个页面各自维护自己的操作入口,这样当我们需要测试一个流程时,只需要把经过的页面对应的操作组装到一起就可以了,当我们需要更新某一个页面的某个操作时,只需要去页面对应的类中去修改指定的操作,而不影响原有的流程化逻辑,具体请参考源码。

Demo实例

广告时间结束,正片从这里开始。

上面讲了这么多内容做铺垫,相信很多同学已经不耐烦的想要直接看源码了,好的,这就满足泥萌。不过要成功的跑起我们的测试用例来,必须保证本机已经配置好了Macaca的相关环境,还没配置的同学请参考我上一篇文章Macaca-Java版入门指南

下载源码 github地址

$ git clone https://github.com/Yinxl/bootstrap.git

更新依赖

$ cd bootstrap
$ mvn -s settings.xml clean install

如果下载依赖过程中报错,可能是由于mvn -s命令没有生效导致的,建议将根目录下settings.xml中的依赖配置到本地Maven目录下的settings.xml中。

如何修改目标平台 ios/android?

//package com.javademo.common;
// Config.java
 // 目标平台- ios android 
   public static final String PLATFORM = "ios"; 

注意:执行iOS用例时需要将XCode升级到最新的8.1,执行用例前请先启动目标模拟器。

启动server

$ macaca server --verbose

注意启动server时不能加代理,因为server在本机启动需要连接localhost,加代理会导致无法建立连接。

执行测试用例

$ mvn test 

Demo详解

如果你成功跑起来了用例,那么下一步我们就来详细研究一下Demo的源码部分了,如果你非常不幸的因为各种原因没能run起来,请先保证Macaca的环境已经正常安装(macaca-doctor),如果环境正常但还是启动失败,请毫不吝啬的联系我。

下面给出一张各package的作用讲解,在看过这部分之后相信大部分人已经基本清楚这个框架的基础结构了,然后更深入的理解,还需要大家认真去研究一下源码。
bootstrap

To Do

1. 数据驱动实现

目前的框架已经解决了一些自动化测试用例编写中的基本问题,但是在写过一定量的case后,我们会发现case的组装实际上是一种类似的逻辑:获取控件(通过多种方式) -> 对控件进行某种操作(click)->与预期结果进行对比得到case执行结果,这有限的几种,既然这些操作如此相似,那我们是不是可以通过一种数据驱动的方式更有效的进行case的管理,就像如下这张图这样:
_2016_09_23_11_24_45
最后我们期望达到的效果是建立一个管理系统,将所有的流程通过用例管理系统进行如上信息的管理,最终实现零编码的自动化用例设计,当然这其中还需要解决诸多问题,需要我们在积累编写经验的同时不断完善。也欢迎志同道合的同学们加入到这个过程中一起努力!

2. 与网络数据的结合

想象一下我们的自动化测试工作已经正常投产,然后在运行过程中我们发现了一些bug,这时候开发就需要去解决这些bug,对于开发同学,我们现在能提供的是bug出现时的屏幕截图,但是很多时候仅仅依赖一个截图是不能帮助开发同学去定位真正的问题的,如果能获取用户当时的请求和后端的返回数据,结合屏幕截图,则能大大的方便开发同学定位并解决问题,这一步要如何实现,还需要我们进一步的思考。如果这一步完成了,那么我们相当于将线上巡检与UI自动化结合在了一起,无疑是一件很有意义的大跨越。

除了网络数据,还有很多可以和UI自动化结合的点子,比如埋点,比如监控,因为UI操作是一切app行为的基础,所以从UI自动化出发,我们有很多事情可以做,有没有热血沸腾了呢?

目录
相关文章
|
12天前
|
Java 调度
Java并发编程:深入理解线程池的原理与实践
【4月更文挑战第6天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将从线程池的基本原理入手,逐步解析其工作过程,以及如何在实际开发中合理使用线程池以提高程序性能。同时,我们还将关注线程池的一些高级特性,如自定义线程工厂、拒绝策略等,以帮助读者更好地掌握线程池的使用技巧。
|
14天前
|
前端开发 编解码 数据格式
浅谈响应式编程在企业级前端应用 UI 开发中的实践
浅谈响应式编程在企业级前端应用 UI 开发中的实践
15 0
浅谈响应式编程在企业级前端应用 UI 开发中的实践
|
28天前
|
安全 Java 调度
Java中的多线程编程:从理论到实践
【2月更文挑战第30天】本文旨在深入探讨Java中的多线程编程。我们将从基础的理论出发,理解多线程的概念和重要性,然后通过实际的Java代码示例,展示如何创建和管理线程,以及如何处理线程间的同步和通信问题。最后,我们还将讨论Java并发库中的一些高级特性,如Executor框架和Future接口。无论你是Java初学者,还是有经验的开发者,本文都将为你提供有价值的见解和实用的技巧。
|
13天前
|
Java 程序员 调度
Java中的多线程编程:基础知识与实践
【4月更文挑战第5天】 在现代软件开发中,多线程编程是一个不可或缺的技术要素。它允许程序员编写能够并行处理多个任务的程序,从而充分利用多核处理器的计算能力,提高应用程序的性能。Java作为一种广泛使用的编程语言,提供了丰富的多线程编程支持。本文将介绍Java多线程编程的基础知识,并通过实例演示如何创建和管理线程,以及如何解决多线程环境中的常见问题。
|
9天前
|
Java 数据挖掘
java实践
【4月更文挑战第9天】java实践
12 1
|
24天前
|
运维 监控 持续交付
构建高效自动化运维体系:策略与实践
在数字化时代,企业IT基础设施的管理和维护变得日益复杂。为了提高效率、降低错误率并快速响应市场变化,构建一个高效的自动化运维体系至关重要。本文将探讨自动化运维的核心策略,并通过实际案例分析展示如何将这些策略应用于日常管理中,以实现IT运维的优化。
15 0
|
1天前
|
负载均衡 Java 开发者
细解微服务架构实践:如何使用Spring Cloud进行Java微服务治理
【4月更文挑战第17天】Spring Cloud是Java微服务治理的首选框架,整合了Eureka(服务发现)、Ribbon(客户端负载均衡)、Hystrix(熔断器)、Zuul(API网关)和Config Server(配置中心)。通过Eureka实现服务注册与发现,Ribbon提供负载均衡,Hystrix实现熔断保护,Zuul作为API网关,Config Server集中管理配置。理解并运用Spring Cloud进行微服务治理是现代Java开发者的关键技能。
|
1天前
|
网络协议 Java API
深度剖析:Java网络编程中的TCP/IP与HTTP协议实践
【4月更文挑战第17天】Java网络编程重在TCP/IP和HTTP协议的应用。TCP提供可靠数据传输,通过Socket和ServerSocket实现;HTTP用于Web服务,常借助HttpURLConnection或Apache HttpClient。两者结合,构成网络服务基础。Java有多种高级API和框架(如Netty、Spring Boot)简化开发,助力高效、高并发的网络通信。
|
2天前
|
运维 Kubernetes Devops
构建高效自动化运维体系:DevOps与容器技术融合实践
【4月更文挑战第15天】 在当今快速发展的信息技术时代,传统的IT运维模式已难以满足业务敏捷性的需求。本文旨在探讨如何通过整合DevOps理念和容器技术来构建一个高效的自动化运维体系。文章将详细阐述DevOps的核心原则、容器技术的基础知识,以及两者结合的优势。此外,文中还将分享一系列实践经验,包括持续集成/持续部署(CI/CD)流程的搭建、微服务架构的应用,以及监控和日志管理策略的优化,以期帮助企业实现快速、可靠且安全的软件交付过程。
|
3天前
|
测试技术 持续交付 Docker
Django中的自动化部署与持续集成实践
【4月更文挑战第15天】本文介绍了Django项目中自动化部署与持续集成的实践方法。自动化部署通过选择Ansible、Fabric或Docker等工具,编写部署脚本,配置持续集成工具(如Jenkins、GitLab CI),确保服务器环境一致,实现快速应用上线。持续集成则涉及配置版本控制系统,设置自动化构建和测试,编写全面的测试用例,集成代码质量检查工具,并配置通知机制,以提升代码质量和开发效率。这两者结合能有效提升项目的迭代速度和可靠性。