APP 自动化框架设计分享

在分享前 首先先祝大家新年快乐,再祝 testerhome 继续这样越来越好~~

前言:

最近几个月都很忙,这一陈会延续到明年4月~~元旦都在加班~所以我很”焦灼“!
下面是分享的这个是我个人的想法,可能大家觉得不合理的地方都可以提出来,我会虚心接纳大家的建议~!大家互勉~谢谢!

框架需要解决的问题:

• 渠道包->多渠道包核心用例自动化

• 多设备覆盖安装,安装卸载更新等测试

• 多设备核心用例适配测试

• 验证主要页面(包括 webview)检查是否加载成功

• 离线主流程覆盖

• 一些重复性操作可以通过框架简单实现

框架目标定位:

• 让 Tester 无需编写代码 通过简单数据驱动方式实现通用简单的自动化

• 跟开发约定一些 UI 上的元素标准和规范建立自动化规范流程化

• 结合实时抓包组件和性能监控插件方便分节点定位问题

• 自动异常捕获,CrashLog 收集汇总等等

• 每一步都有 Log、截图(甚至做到录制)方便复现问题

• 实行单台服务器多设备并行 根据配置不同机型执行不同 case 并统一会汇总报告

关于自动化的一些疑问:

--->自动化的时候用例错误了怎么办?下面的会继续跑么?

当发生错误时会优先检查检查设备状态,网络状态当用例发生错误时(如果是webview会等待20秒刷新页面)回到上一步等待30s切换回来重复执行,如果还是发生错误会在报告说明,继续执行下一条用例

--->我们怎么去用这个东西呢?数据我们怎么去准备?数据准备麻烦么?

当测试人员有自动化测试需求时只需要配置好数据模板在网页选择执行的机器点击开始运行即可


数据准备:数据准备为每一个自动化测试工程师的难题,因为每一步动作都需要用uiautomatorviewer  或者hierarchyviewer 去一个一个找元素
针对这个我们解决方法是:跟开发约定界面控件命名规范,元素控件值按我们约定的格式命名   只需打开app找到需要点击控件名称的首字母填入文档中即可(当然这种办法只会解决部分问题)

自动化跑完之后如果发生异常了怎么办?自动化跑完之后发生异常我们如何分析?

根据目前设计的框架,三种定位问题的方法:

>1,第一是跑自动化时会实时抓取Devices设备所有logcat日志并解析异常Log(包括crash日志)

>2,第二是跑自动化时会实时截取实时app发送的所有API的内容以及状态方便定位区分前后端问题

>3,第三是跑自动化时会实时截图甚至可以录制视频,还有测试人员自定义的一些检查点作为主要的定位路径

关于 UI 控件命名规范::

跟开发约定界面控件命名规范,元素控件值按我们约定的格式命名 这样可以提高自动化效率,以及减轻版本迭代自动化工作量!
以下示例:

以页面为整体 控件为类型 各类型的控件拼音首字母为控件标识 统一格式为:应用缩写页面名称控件类型_控件首字母

button格式:

比如主页的搜索按钮 控件的格式为:TT_Home_ button_Ss

Input 格式:

比如登录页面用户名输入框:TT_Login_input_Zh

image格式:

比如推荐页面图片“每日十首”:TT_ Recommend_ image_mrss

这样的好处就是我们不需要用 uiautomatorviewer 或者 hierarchyviewer 去一个一个找元素 碰到需要点击的元素控件只需要根据页面上的控件首字母,就算页面改动我们也只需要对着 app 上面在模板内改动的部分修改一下数据即可~

流程图:

用户需要执行:
根据元素设计case 
制定预期
选择机型并开始运行

启动 log:

环境初始化:

Appium 启动封装起来,在每次启动前 检查初始化端口以及adb进程  再分配 Port  和BootPort

AndroidDevices Capabilities  里面四个可变量参数可以通过adb取到(device 列表和对应的型号放在Map内)

设计一个 DriverModel

package org.alimusic.driver;

public class DriverModel {
    private String device="Android";
    private String deviceName;
    private String platformName="Android";
    private String platformVersion;
    private String appPackage="com.xxx.ttpod";
    private String appActivity="com.xxx.ttpod.EntryActivity";
    public String getDevice() {
        return device;
    }
    public void setDevice(String device) {
        this.device = device;
    }
    public String getDeviceName() {
        return deviceName;
    }
    public void setDeviceName(String deviceName) {
        this.deviceName = deviceName;
    }
    public String getPlatformName() {
        return platformName;
    }
    public void setPlatformName(String platformName) {
        this.platformName = platformName;
    }
    public String getPlatformVersion() {
        return platformVersion;
    }
    public void setPlatformVersion(String platformVersion) {
        this.platformVersion = platformVersion;
    }
    public String getAppPackage() {
        return appPackage;
    }
    public void setAppPackage(String appPackage) {
        this.appPackage = appPackage;
    }
    public String getAppActivity() {
        return appActivity;
    }
    public void setAppActivity(String appActivity) {
        this.appActivity = appActivity;
    }

    public DriverModel(String device, String deviceName,String platformName,String platformVersion) {
        super();
        this.device = device;
        this.deviceName = deviceName;
        this.platformName = platformName;
        this.platformVersion = platformVersion;

    }

    public DriverModel(String deviceName,String platformVersion) {
        super();
        this.deviceName = deviceName;
        this.platformVersion = platformVersion;

    }

    public DriverModel() {
        super();
        // TODO Auto-generated constructor stub
    }
}

Factory(三种情况):


package org.alimusic.driver;

import io.appium.java_client.android.AndroidDriver;


/**
 * 
 * @author testly
 *
 */
public class DrvierSetting {



    public abstract class Factory{
        public abstract DriverModel createDriverModel();
        public abstract DriverModel createDriverModel(String device,String deviceName,String platformVersion,String platformName);
    }

    public static class SimpleFactory{
        public DriverModel createDriverModel() {
            DriverModel model = new DriverModel();
            return model;
        }

        public static DriverModel createDriverModel(String device,String deviceName,String platformVersion,String platformName){
            DriverModel model = new DriverModel(device,deviceName,platformVersion,platformName);
            AndroidDriver driver = DrvierStart.Start(model);
            return model;
        }

        public static DriverModel createDriverModel(String deviceName,String platformVersion){
            DriverModel model = new DriverModel(deviceName,platformVersion);
            return model;
        }
    }
}


Derices StartUp


public static AndroidDriver Start(String devicename,String ip, int port)
       {       
           AndroidDriver driver = null;
           String platformName = GetEnvironmentVariable.DevicesVersion(devicename);
           DriverModel model = SimpleFactory.createDriverModel(devicename,platformName);
           DesiredCapabilities capabilities = new DesiredCapabilities(); 
           capabilities.setCapability("device",model.getDevice());
           capabilities.setCapability("deviceName",model.getDeviceName());              
           capabilities.setCapability("platformVersion", model.getDeviceName());  
           capabilities.setCapability("platformName",model.getDeviceName());  
           capabilities.setCapability("appPackage", model.getAppPackage());  
           capabilities.setCapability("appActivity", model.getAppActivity());
           try {
               driver = new AndroidDriver(new URL("http://”+ip+“:“+port+“/wd/hub"), capabilities);
           } catch (MalformedURLException e) {
               System.out.println("connection error!");
               e.printStackTrace();
           }
           return driver;

      }    

数据配置定制:

前台网页 会根据用户选择配置去自动设置配置文件

检查:

检查是我认为最难!~

目前我的设想是:

1,用户自定义检查
2,网络传输层检查(自动化时实时抓包)
3,logcat实时抓取异常log(区粉设备)
4,截图录制、系统抛错,图片解析对比等

通过遍历文件内的数据文件的一条数据既是一个动作和检查点

欢迎一起交流,一起进步 可以关注我的微信公众号:“测试开发进阶” - 点我关注


↙↙↙阅读原文可查看相关链接,并与作者交流