python 群控源代码_自动化 带你用 Python 实现自动化群控设备 _好机友
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 名称显示出来
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 文件,利用正则表达式得到目标控件的坐标值
计算出控件的中心点坐标
利用控件 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 自动化群控最简单的实现方式,后面将和大家讨论更加复杂的实现方式。
我已经将文中全部源码上传到后台,关注公众号后回复「 qk 」即可获得全部源码
如果你觉得文章还不错,请大家 点赞、分享、留言下,因为这将是我持续输出更多优质文章的最强动力!
python 群控源代码_自动化 带你用 Python 实现自动化群控设备 _好机友相关推荐
- 十三、写了两年多Python文章的我,带你走进Python数据分析
@Author : By Runsen @Date : 2020/5/13 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘 ...
- python基础入门(Peak带你学python)
带你学python Peak带你学python 基础语法知识 print函数 转义字符 进制转换 保留字和标识符 变量 数据类型 数据类型转换 注释 input函数 运算符 运算符优先级 布尔值 if ...
- python必备源代码-资源推荐|347个Python开发经典资源推荐(42类)
原标题:资源推荐|347个Python开发经典资源推荐(42类) 今天的文章是Python开发资源,总计42个大类,一共347项.(Python的东西实在太多了,一个人整理简直是自寻死路,大家如果有比 ...
- 这是我见过最好的Python教程:十分钟带你认识Python
这篇文章主要介绍了简洁的十分钟Python入门教程,Python语言本身的简洁也使得网络上各种Python快门入门教程有着很高的人气,本文是国内此类其中的一篇,需要的朋友可以参考下 [简介] Pyth ...
- 【Python发展前景】一篇文章带你了解Python未来发展“钱”景
前言 计算机语言发展至今,已出现众多的编程语言.例如入门较难的C语言,相对通用的Java,适合初学者的Basic语言等. 但自从Python横空出世以来,以其简洁优美.功能强大.开发效率高等先天优势, ...
- python数据抓取技术与实战训练_师傅带徒弟学Python:项目实战1:网络爬虫与抓取股票数据...
本视频基于**Python 3.X版本 本视频课程是第四篇第一个实战项目,内容包括网络爬虫技术.使用urllib爬取数据.使用Selenium爬取数据.使用正则表达式.使用BeautifulSoup库 ...
- python 传奇服务端_夜光带你走进python开发 (三十二)传奇语言
夜光序言: 夜光越长大,越知道做事不容易,越知道每个人都有难处,也就越不敢随随便便的瞧不起谁,以免不小心伤害了谁. 这当然不是粉饰,更不是虚伪,而是懂得了体谅和温柔,温柔的和这个世界相处. 正文:文件 ...
- python list find_一篇文章带你了解Python爬虫常用选择器
原创 麦自香 Python爬虫案例 当我们初学爬虫的时候,我们都会选择一些最基本的网站,往往不带任何反爬措施.比如某个博客站点,我们要爬全站的话,就顺着列表页爬到文章页,再把文章的时间.作者.正文等信 ...
- python的源代码文件的扩展名是-python源文件后缀是什么?
python源文件后缀是py. 以 py 扩展名的文件是 Python 源码文件,由 python.exe 解释,可在控制台下运行.可用文本编辑器读写. Python中经常使用的文件后缀名: pyc ...
最新文章
- 百度阿里华为资深AI工程师薪资一览,有多大能力拿多少钱
- Redis源码研究—基础知识
- linq学习笔记(2):DataContext
- 学习笔记#Android Studio 从安装到虚拟机启动
- openstack下
- seata xid是什么_阿里开源的分布式事务框架 Seata
- java集合框架05——ArrayList和LinkedList的区别
- 硬解析和软解析 mysql_Oracle学习之shared pool--硬解析和软解析
- php学习笔记0001 变量作用域
- ASP.NET知识点
- 用python画图代码-【Matplotlib】利用Python进行绘图
- Docker容器中运行Ubuntu系统
- datatable的查询介绍
- mysql修改、删除数据记录
- XP 远程连接window 2008 网络级别身份验证问题解决方法
- Webpack5构建微前端和Web应用程序2022教程
- yuv420转rgba
- 第三届红帽杯网络安全攻防大赛官方WP
- Geos库在Windows上的编译
- 极简教程!教你快速将K3s与Cloud Controller集成