一 简单说两句

数月之前,在我刚完成 MAT 平台并信心满满的放出推介文章之后,就着手在公司落地,可惜的是因为种种原因落地失败了,一方面是我的失误,另一方面是在一个技术环境差的状态下一个小喽啰想改变些什么的无力,此项目就当作学习以及帮助学习的东西吧,你们可以尽情的嘲笑我,能给大家带来欢乐我特么的也满足了,至少有那么点用了😓 😭 没看过的同学可以先去熟悉一下 MAT 平台,当然经过一系列优化,目前 MAT 的操作体验要优于之前写推介帖子的时候。
【MAT 简介文章】-->MAT:远程测试机&自动化调试执行机之 web 平台
【MAT 安装操作指南】-->MAT:安装及操作指南
【开源地址】-->open-MAT

二 总体设计概述

因为 MAT 平台从思路到设计再到实现完全由我一人独立实现,所以整体设计充分体现了拍脑袋的设计方法,欢迎拍砖欢迎来喷。
1.MAT 平台由Django搭建;
2.投屏&远程操控的插件来自于 open-STF 的minicap&minitouch (社区有充分的文章,不懂的同学可以自行社区搜索)
3.投屏&远程控制的异步任务由 python 异步分布式框架 Celery 支持,异步队列应用 redis 实现 (理论上 MAT 由于 Cerely 和 redis 的加持是支持分布式的设备连接)
4.集成 Appium 及 UI Automator Viewer 集成到 web 上支持远程调试 Appium 及运行 Appium 脚本 (当然你也可以把 Appium 换成其他 UI 框架,只需更改极少的代码)

三 关键代码分析

要承认 MAT 平台的 python 代码并不多,大量的 JavaScript 代码,甚至让 github 都认为我这是 JavaScript 项目。。

1.启动 minicap&minitouch 的代码分析

2.启动 admin 模式

因为 MAT 平台是开放访问的,并且后台系统没有启用,所以我就搞了个偷鸡的方式,按 shift + <--(方向键 - 右) 启动 admin 模式,在此模式下你可以随意关闭其他人的投屏普通模式下是不允许关闭非本页面打开的投屏的。js 实现,由于代码过于分散,详情请参考位置 /MAT/apps/appcrawler/templates/app_c.html 第 96 行

3.半小时未操作自动关闭投屏

前期试用时老是有人用完不关闭投屏,导致资源浪费,故我通过 js 监控投屏的画布的鼠标动作来监控用户操作计时,当达到 30 分钟用户无操作将自动发起 ajax 移步关闭投屏的请求,自动关闭投屏,释放资源,js 代码同样分散到整个代码里,所以就不展示来,详情请参考位置 /AT/apps/appcrawler/templates/myframe.html 第 189 行

4.web 化 UI Automator Viewer

实现原理:adb 获取当前页面 xml,应用 python-xml 解析 xml 文件,生成 ul li 标签返回给前台,并遍历所有元素生成元素详情清单 yml 文件
详情代码如下:代码位置 /MAT/apps/appcrawler/UIAutomationView.py

# -*- coding: UTF-8 -*-
import xml.etree.ElementTree as ET
import yaml
import os

# 全局唯一标识
unique_id = 0
def write_yaml(json, path):
    # 写
    if type(json) != dict:
        json = eval(json)
    with open(path, 'w+') as f:
        yaml.dump(json, f, default_flow_style=False, allow_unicode=True, encoding='utf-8')

def read_yaml(path):
    # 读取案例yaml数据
    with open(path, 'r') as f:
        return yaml.load(f)

# 遍历所有的节点
def walkData(root_node, level, result_list, file_name, myyaml):
    ul = '<ul id="%s"><li id="%s">%s:%s%s</li>'
    global unique_id
    try:
        cls = root_node.attrib['class'].split('.')[-1]
        text = root_node.attrib['text']
    except:
        cls = root_node.tag
        text = ''
    if root_node.attrib.has_key('bounds'):
        ul_temp = ul % (level, unique_id, cls, text, root_node.attrib['bounds'])
    else:
        ul_temp = ul % (level, unique_id, cls, text, '[][]')
    result_list.append(ul_temp)
    myyaml.__setitem__(unique_id, root_node.attrib)
    # 全局唯一标识,递增
    unique_id += 1
    # 遍历每个子节点
    children_node = root_node.getchildren()
    if len(children_node) == 0:
        result_list.append('</ul>')
        write_yaml(myyaml, file_name)
        return
    for child in children_node:
        walkData(child, level + 1, result_list, file_name, myyaml)
    result_list.append('</ul>')
    write_yaml(myyaml, file_name)
    return result_list

# 获得原始数据
# out:
# <ul><li><span>xx</span></li></ul>
def getXmlData(file_name, name):
    level = 0  # 节点的深度从0开始
    myyaml = {}
    result_list = []
    root = ET.parse(file_name).getroot()
    os.remove(file_name)  #清除xml文件
    # yml
    file_name = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
                             'appcrawler/UIxml/%s.yml' % str(name))
    walkData(root, level, result_list, file_name, myyaml)
    # 运行结束,归0
    unique_id = 0
    return ''.join(result_list)

篇幅有限,代码方面就说这么多吧

四 功能填充

MAT 平台到此时已经具备了云真机的基础功能 (实时远程操控),当然我们的初衷是结合 MAT 平台远程真机操控给它扩充更多实用功能,目前已经完成 UIAutomateViewer 的 web 化以及远程调试 Appium 及运行 Appium 脚本 (当然你也可以把 Appium 换成其他 UI 框架,只需更改极少的代码),还有一些其他辅助性功能,就不赘述了,相信 python 高手很多,Django 版的 MAT 开源作为抛砖引玉可能会给我们带来很多惊喜,当然这也可能这只是我的一厢情愿。

五 已知问题

目前已知的最大问题就是 cerely&redis 构建的异步任务承受不了很大的压力 (同时远程使用 8 台以上云真机),服务器会发烫严重,甚至有宕机的风险,我对这方面了解不深,希望有了解的同学可以参与进来与我共同优化 MAT 云真机平台。还有就是之前所说的 MAT 重要组件,flutter 版 MAT app,作用是把远程真机投屏到移动端供远程操控,因为落地失败,还有技术问题搁置了,希望有 flutter 开发经验的小伙伴参与进来。当然除了上述已知问题,还有很多很多的问题,希望同道中人与我联系,共同学习,共同进步。

六 开源及说明

目前代码已提交github 点击跳转,第一次开源项目,欢迎 star,欢迎提 issues。


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