python实现自动化群控的步骤


Posted in Python onApril 11, 2021

1. 前言

群控,相信大部分人都不会陌生!印象里是一台电脑控制多台设备完成一系列的操作,更多的人喜欢把它和 Hui 产绑定在一起!

事实上,群控在自动化测试中也被广泛使用!接下来的几篇文章,我将带大家聊聊企业级自动化中,群控正确的使用姿势!

本篇先从基础篇开始,聊聊使用「 Python + adb 」命令如何编写一套群控脚本

2. 准备

在本机安装 Android 开发环境,保证 adb 被添加到环境变量

将准备好的多台设备,使用数据线( 或者通过 Hub )连接到电脑上

通过 adb devices 命令查看已经连接的所有设备

# 下面显示连接了3台设备
xag:Test xingag$ adb devices
List of devices attached
822QEDTL225T7    device
ca2b3455        device
DE45d9323SE96   device

3. 实战

自动化群控以闲鱼 App 的一次关键字搜索为例,步骤包含:打开应用、点击到搜索界面、输入内容、点击搜索按钮
下面通过7步来完成这一操作

1、获取目标应用的包名及初始化 Activity

获取方式有很多种,主流方式包含:adb 命令、解析 APK、第三方 APK、无障碍服务
这里推荐使用 adb 命令这种方式

# 获取当前运行应用的包名及初始Activity
adb shell dumpsys activity | grep -i run

打开闲鱼 App,在命令终端输入上面的命令,终端会将包名及 Activity 名称显示出来

python实现自动化群控的步骤

2、获取所有在线的设备

通过 adb devices 命令,通过输出内容,进行一次过滤,得到所有连接到 PC 端的设备

# 所有设备ID
devices = []

def get_online_devices(self):
    """
    获取所有在线的设备
    :return:
    """
    global devices
    try:
        for device_serias_name in exec_cmd("adb devices"):
           # 过滤掉第一条数据及不在线的设备
           if "device" in device_serias_name:
              devices.append(device_serias_name.split("\t")[0])
           devices = devices[1:]
    except Exception as e:
            print(e)

    # 连上的所有设备及数量
    return devices

3、群控打开目标应用

遍历设备列表,使用 adb -s 设备ID shell am start -W 命令分别打开目标应用

def start_app(self):
    """
    打开App
    :return: 
    """
    for device in devices:
        os.popen("adb -s " + device + " shell am start -W {}/{}".format(self.packageName, self.home_activity))
    print('等待加载完成...')
    sleep(10)

4、封装执行步骤

为了方便管理设备,将每一步的操作写入到YAML文件中,可以通过 ID 查找元素并执行点击操作、在输入框中输入内容、调用本地方法及输入参数
这里分别对应:保存 UI 树控件、查找输入框元素并执行点击操作、保存 UI 树控件(界面变化了)、输入文本内容、查看搜索按钮元素并执行点击操作

# steps_adb.yaml

# 包名和Activity
package_name:  com.taobao.idlefish
home_activity:  com.taobao.fleamarket.home.activity.InitActivity

# 执行步骤
steps:
  - save_ui_tree_to_local:
      method:  save_ui_tree_to_local
      args:
  - find_element_and_click:
      id:  com.taobao.idlefish:id/tx_id
  - save_ui_tree_to_local:
      method:  save_ui_tree_to_local
  - input_content:
      content:  Python
  - find_element_and_click:
      id:  com.taobao.idlefish:id/search_button

需要指出的是,为了提高群控的适配性,控件的实际坐标需要通过下面的步骤去获取:

  • 导出界面的控件树
  • 解析控件树 XML 文件,利用正则表达式得到目标控件的坐标值
  • 计算出控件的中心点坐标

python实现自动化群控的步骤

利用控件 ID 获取元素中心点坐标的实现代码如下:

def get_element_position(element_id, uidump_name):
    """
    通过元素的id,使用ElementTree,解析元素控件树,查找元素的坐标中心点
    :param element_id: 元素id,比如:
    :return: 元素坐标
    """

    # 解析XML
    tree = ET.parse('./../%s.xml' % uidump_name)
    root = tree.getroot()

    # 待查找的元素
    result_element = None

    # print('查找数目', len(root.findall('.//node')))

    # 遍历查找node元素
    # 通过元素id
    for node_element in root.findall('.//node'):
        if node_element.attrib['resource-id'] == element_id:
            result_element = node_element
            break

    # 如果找不到元素,直接返回空
    if result_element is None:
        print('抱歉!找不到元素!')
        return None

    # 解析数据
    coord = re.compile(r"\d+").findall(result_element.attrib['bounds'])

    # 中心点坐标
    position_center = int((int(coord[0]) + int(coord[2])) / 2), int((int(coord[1]) + int(coord[3])) / 2)

    return position_center

5、区分设备

为了保证群控脚本执行不会产生干扰,在每个步骤执行之前,都应该将设备 ID 作为参数进行区分
比如:将控件的界面控件树按照设备保存为不同的名称、点击界面和输入的命令传相应设备 ID 作为入参

def save_ui_tree_to_local(dName):
    """
    获取当前Activity控件树,保存到本地
    文件名固定为:uidump.xml
    :param dName: 设备id
    :return:
    """

    exec_cmd("adb  -s %s shell uiautomator dump /data/local/tmp/%s.xml" % (dName, dName))

    sleep(2)

    exec_cmd("adb -s %s pull /data/local/tmp/%s.xml ./../" % (dName, dName))

6、执行步骤

从 YAML 文件中读取执行步骤,遍历步骤集合,内部遍历设备列表,以保证每一个步骤,分别执行到每台设备上

# 执行步骤
for step in self.steps:
    # 设备
    for device in devices: 
        pass

接着,通过步骤名称匹配不同的操作,即可操作设备了

# 操作名称
step_name = list(step)[0]

if step_name == 'save_ui_tree_to_local':
    # 保存UI数到本地
    method = step.get(step_name).get('method')
    save_ui_tree_to_local(device)
elif step_name == 'find_element_and_click':
    element_id = step.get(step_name).get('id')
    # 获取元素的坐标
    bound_search_input = get_element_position(element_id, device)
    # 点击元素
    exec_cmd('adb -s %s shell input tap %s %s' % (device, bound_search_input[0], bound_search_input[1]))
elif step_name == 'input_content':
    input_content = step.get(step_name).get('content')
    # 模拟输入
    exec_cmd('adb -s %s shell input text %s' % (device, input_content))
else:
    print('其他操作步骤')

7、关闭应用

当所有的操作完成之后,同样是遍历设备,利用 adb 命令去关闭 App 即可

def stop_all(self):
   """
   关闭应用
   :return:
   """
   for device in devices:
       os.popen("adb -s " + device + " shell am force-stop  %s" % self.packageName)

4. 最后

本篇仅仅是 Python 自动化群控最简单的实现方式,后面将和大家讨论更加复杂的实现方式。

项目地址:https://github.com/xingag/test_auto/tree/master/group_control

以上就是python实现自动化群控的步骤的详细内容,更多关于python 自动化群控的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python实现合并两个数组的方法
May 16 Python
python实现爬取千万淘宝商品的方法
Jun 30 Python
浅谈python字典多键值及重复键值的使用
Nov 04 Python
python xml.etree.ElementTree遍历xml所有节点实例详解
Dec 04 Python
Python 使用os.remove删除文件夹时报错的解决方法
Jan 13 Python
python实现任意位置文件分割的实例
Dec 14 Python
python 工具 字符串转numpy浮点数组的实现
Mar 14 Python
Python制作一个仿QQ办公版的图形登录界面
Sep 22 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
Nov 05 Python
python读取图片颜色值并生成excel像素画的方法实例
Feb 19 Python
python实现web邮箱扫描的示例(附源码)
Mar 30 Python
python 三边测量定位的实现代码
Apr 22 Python
python 调用js的四种方式
Apr 11 #Python
Python WSGI 规范简介
使用pytorch实现线性回归
pytorch实现线性回归以及多元回归
python如何获取网络数据
Apr 11 #Python
Pytorch 使用tensor特定条件判断索引
selenium.webdriver中add_argument方法常用参数表
Apr 08 #Python
You might like
PHP添加MySQL数据记录代码
2008/06/07 PHP
php 远程关机操作的代码
2008/12/05 PHP
过滤掉PHP数组中的重复值的实现代码
2011/07/17 PHP
解决PHP mysql_query执行超时(Fatal error: Maximum execution time …)
2013/07/03 PHP
php构造函数实例讲解
2013/11/13 PHP
解决Codeigniter不能上传rar和zip压缩包问题
2014/03/07 PHP
thinkPHP框架动态配置用法实例分析
2018/06/14 PHP
javascript web对话框与弹出窗口
2009/02/22 Javascript
javascript getElementsByTagName
2011/01/31 Javascript
jQuery插件实现屏蔽单个元素使用户无法点击
2013/04/12 Javascript
ajax读取数据后使用jqchart显示图表的方法
2015/06/10 Javascript
JavaScript中函数(Function)的apply与call理解
2015/07/08 Javascript
详解JS数值Number类型
2018/02/07 Javascript
vue.js打包之后可能会遇到的坑!
2018/06/03 Javascript
详解Node.js 中使用 ECDSA 签名遇到的坑
2018/11/26 Javascript
小程序点击图片实现自动播放视频
2020/05/29 Javascript
javascript刷新父页面方法汇总详解
2019/10/10 Javascript
JavaScript 变量,数据类型基础实例详解【变量、字符串、数组、对象等】
2020/01/04 Javascript
[01:04]DOTA2上海特锦赛现场采访 FreeAgain遭众解说围攻
2016/03/25 DOTA
centos下更新Python版本的步骤
2013/02/12 Python
Python读取英文文件并记录每个单词出现次数后降序输出示例
2018/06/28 Python
从运行效率与开发效率比较Python和C++
2018/12/14 Python
Python生命游戏实现原理及过程解析(附源代码)
2019/08/01 Python
使用Python制作缩放自如的圣诞老人(圣诞树)
2019/12/25 Python
全球领先的美容用品专卖店:Beauty Plus Salon
2018/09/04 全球购物
英国家电购物网站:Sonic Direct
2019/03/26 全球购物
HQhair美国/加拿大:英国化妆品、美容及美发产品商城
2019/04/15 全球购物
小学生节约用水倡议书
2014/05/15 职场文书
党员批评与自我批评发言材料
2014/10/14 职场文书
少先队辅导员事迹材料
2014/12/24 职场文书
2016新党章学习心得体会
2016/01/15 职场文书
用Python爬虫破解滑动验证码的案例解析
2021/05/06 Python
了解Redis常见应用场景
2021/06/23 Redis
《黑岩★★射手 DAWN FALL》BD发售宣传CM公开
2022/04/04 日漫
Vue OpenLayer 为地图绘制风场效果
2022/04/24 Vue.js
nginx 配置缓存
2022/05/11 Servers