通过python调用adb命令实现用元素名称、id、class定位元素
2017-07-21 00:00
801 查看
在Android自动化测试过程中,使用monkeyrunner可以通过坐标点击某个元素,但缺点是受屏幕分辨率影响,需要随时更改坐标位置。最近有使用了下Appium这个工具,优点是可以通过元素名称、id、class等属性定位,但是需要搭建稍微有点复杂的环境,然后我就想能不能不依赖任何环境,使用纯Python实现通过这几个属性定位,只需要直接执行python脚本就ok?接下来开始着手实现
首先需要Android版本高于4.0,使用这个命令“adb shell uiautomator dump”命令,执行“adb shell uiautomator dump /data/local/tmp/uidump.xml”,然后将该xml文件pull到本地,从里面可以看到手机上当前页面的布局,在note节点下可以找到这些属性:text,resource-id,class,bounds,知道这些内容后就可以使用python对该xml文件解析获取到对应的属性,取出bounds的值,计算出对应元素区域的中心坐标,接着使用adb shell input tap 命令就可以点击该坐标,如果有相同的属性值,那就需要得到一个坐标点的列表,以应用“1号店“为例,在桌面上通过应用名称“1号店”,点击进入应用,然后点击“手机充值”,截图如下:
用python简单实现:
[python]
view plain
copy
#coding=utf-8
import tempfile
import os
import re
import time
import xml.etree.cElementTree as ET
class Element(object):
"""
通过元素定位,需要Android 4.0以上
"""
def __init__(self):
"""
初始化,获取系统临时文件存储目录,定义匹配数字模式
"""
self.tempFile = tempfile.gettempdir()
self.pattern = re.compile(r"\d+")
def __uidump(self):
"""
获取当前Activity控件树
"""
os.popen("adb shell uiautomator dump /data/local/tmp/uidump.xml")
os.popen("adb pull /data/local/tmp/uidump.xml " + self.tempFile)
def __element(self, attrib, name):
"""
同属性单个元素,返回单个坐标元组
"""
self.__uidump()
tree = ET.ElementTree(file=self.tempFile + "\\uidump.xml")
treeIter = tree.iter(tag="node")
for elem in treeIter:
if elem.attrib[attrib] == name:
bounds = elem.attrib["bounds"]
coord = self.pattern.findall(bounds)
Xpoint = (int(coord[2]) - int(coord[0])) / 2.0 + int(coord[0])
Ypoint = (int(coord[3]) - int(coord[1])) / 2.0 + int(coord[1])
return Xpoint, Ypoint
def __elements(self, attrib, name):
"""
同属性多个元素,返回坐标元组列表
"""
list = []
self.__uidump()
tree = ET.ElementTree(file=self.tempFile + "\\uidump.xml")
treeIter = tree.iter(tag="node")
for elem in treeIter:
if elem.attrib[attrib] == name:
bounds = elem.attrib["bounds"]
coord = self.pattern.findall(bounds)
Xpoint = (int(coord[2]) - int(coord[0])) / 2.0 + int(coord[0])
Ypoint = (int(coord[3]) - int(coord[1])) / 2.0 + int(coord[1])
list.append((Xpoint, Ypoint))
return list
def findElementByName(self, name):
"""
通过元素名称定位
usage: findElementByName(u"设置")
"""
return self.__element("text", name)
def findElementsByName(self, name):
return self.__elements("text", name)
def findElementByClass(self, className):
"""
通过元素类名定位
usage: findElementByClass("android.widget.TextView")
"""
return self.__element("class", className)
def findElementsByClass(self, className):
return self.__elements("class", className)
def findElementById(self, id):
"""
通过元素的resource-id定位
usage: findElementsById("com.android.deskclock:id/imageview")
"""
return self.__element("resource-id",id)
def findElementsById(self, id):
return self.__elements("resource-id",id)
class Event(object):
def __init__(self):
os.popen("adb wait-for-device ")
def touch(self, dx, dy):
"""
触摸事件
usage: touch(500, 500)
"""
os.popen("adb shell input tap " + str(dx) + " " + str(dy))
time.sleep(0.5)
def test():
element = Element()
evevt = Event()
e1 = element.findElementByName(u"1号店")
evevt.touch(e1[0], e1[1])
time.sleep(1)
e2 = element.findElementByName(u"手机充值")
evevt.touch(e2[0], e2[1])
这是一个简单的思路,使用的前提是需要开启view server,否则无法获取到uidump.xml这个文件。另外程序运行的会有点慢,可以有优化的方法。
另外如果属性值相同,使用elements,返回的是含坐标元组的列表,如何使用,这里就不讲了。
该文转自:http://blog.csdn.net/gb112211/article/details/33730221
首先需要Android版本高于4.0,使用这个命令“adb shell uiautomator dump”命令,执行“adb shell uiautomator dump /data/local/tmp/uidump.xml”,然后将该xml文件pull到本地,从里面可以看到手机上当前页面的布局,在note节点下可以找到这些属性:text,resource-id,class,bounds,知道这些内容后就可以使用python对该xml文件解析获取到对应的属性,取出bounds的值,计算出对应元素区域的中心坐标,接着使用adb shell input tap 命令就可以点击该坐标,如果有相同的属性值,那就需要得到一个坐标点的列表,以应用“1号店“为例,在桌面上通过应用名称“1号店”,点击进入应用,然后点击“手机充值”,截图如下:
用python简单实现:
[python]
view plain
copy
#coding=utf-8
import tempfile
import os
import re
import time
import xml.etree.cElementTree as ET
class Element(object):
"""
通过元素定位,需要Android 4.0以上
"""
def __init__(self):
"""
初始化,获取系统临时文件存储目录,定义匹配数字模式
"""
self.tempFile = tempfile.gettempdir()
self.pattern = re.compile(r"\d+")
def __uidump(self):
"""
获取当前Activity控件树
"""
os.popen("adb shell uiautomator dump /data/local/tmp/uidump.xml")
os.popen("adb pull /data/local/tmp/uidump.xml " + self.tempFile)
def __element(self, attrib, name):
"""
同属性单个元素,返回单个坐标元组
"""
self.__uidump()
tree = ET.ElementTree(file=self.tempFile + "\\uidump.xml")
treeIter = tree.iter(tag="node")
for elem in treeIter:
if elem.attrib[attrib] == name:
bounds = elem.attrib["bounds"]
coord = self.pattern.findall(bounds)
Xpoint = (int(coord[2]) - int(coord[0])) / 2.0 + int(coord[0])
Ypoint = (int(coord[3]) - int(coord[1])) / 2.0 + int(coord[1])
return Xpoint, Ypoint
def __elements(self, attrib, name):
"""
同属性多个元素,返回坐标元组列表
"""
list = []
self.__uidump()
tree = ET.ElementTree(file=self.tempFile + "\\uidump.xml")
treeIter = tree.iter(tag="node")
for elem in treeIter:
if elem.attrib[attrib] == name:
bounds = elem.attrib["bounds"]
coord = self.pattern.findall(bounds)
Xpoint = (int(coord[2]) - int(coord[0])) / 2.0 + int(coord[0])
Ypoint = (int(coord[3]) - int(coord[1])) / 2.0 + int(coord[1])
list.append((Xpoint, Ypoint))
return list
def findElementByName(self, name):
"""
通过元素名称定位
usage: findElementByName(u"设置")
"""
return self.__element("text", name)
def findElementsByName(self, name):
return self.__elements("text", name)
def findElementByClass(self, className):
"""
通过元素类名定位
usage: findElementByClass("android.widget.TextView")
"""
return self.__element("class", className)
def findElementsByClass(self, className):
return self.__elements("class", className)
def findElementById(self, id):
"""
通过元素的resource-id定位
usage: findElementsById("com.android.deskclock:id/imageview")
"""
return self.__element("resource-id",id)
def findElementsById(self, id):
return self.__elements("resource-id",id)
class Event(object):
def __init__(self):
os.popen("adb wait-for-device ")
def touch(self, dx, dy):
"""
触摸事件
usage: touch(500, 500)
"""
os.popen("adb shell input tap " + str(dx) + " " + str(dy))
time.sleep(0.5)
def test():
element = Element()
evevt = Event()
e1 = element.findElementByName(u"1号店")
evevt.touch(e1[0], e1[1])
time.sleep(1)
e2 = element.findElementByName(u"手机充值")
evevt.touch(e2[0], e2[1])
这是一个简单的思路,使用的前提是需要开启view server,否则无法获取到uidump.xml这个文件。另外程序运行的会有点慢,可以有优化的方法。
另外如果属性值相同,使用elements,返回的是含坐标元组的列表,如何使用,这里就不讲了。
该文转自:http://blog.csdn.net/gb112211/article/details/33730221
相关文章推荐
- 通过python调用adb命令实现用元素名称、id、class定位元素
- 通过python调用adb命令实现用元素名称、id、class定位元素
- 通过python调用adb命令对app进行性能测试(6 -2)
- Adb-For-Test 使用 adb 命令实现元素定位等功能,用来辅助 android 测试
- Python调用adb命令实现对多台设备同时进行reboot
- Python调用adb命令实现对多台设备同时进行reboot的方法
- Python如何通过subprocess调用adb命令详解
- 通过python调用adb命令对app进行性能测试(6 -1)
- 实现可以通过adb命令获取Android手机的IP地址
- Python调用DLL实现部分ADB功能
- python调用外部子进程,通过管道实现异步标准输入和输出
- Python手机开发调用DLL实现部分ADB功能
- python调用外部子进程,通过管道实现异步标准输入和输出的交互
- novaclient代码解析之---通过nova show <server-id>命令解析Nova client与Nova API之间的调用关系
- Android通过adb命令实现模拟滑动
- Winform中通过一个字符串定位到和字符串相等ID的控件(将字符串转换成相应的控件名称)
- 在windows下使用cmd命令通过adb shell自动调用android模拟或真机的InstrumentRunner进行android 自动化测试
- python调用Moxa PCOMM Lite通过串口Ymodem协议实现发送文件
- document.getElementsByClassName:简单的原生通过className查找元素,可指定多个样式名称进行查找
- js通过元素class名字获取元素集合的具体实现