篇11 python自动化测试应用-python调用安卓adb命令(下篇)
--lamecho辣么丑
1.1概要
大家好!我是lamecho(辣么丑),今天是《python自动化测试应用》的第十一篇,本篇将继续第十篇的adb命令结合pyapp框架编写过程中实际遇到的那些坑。后面的内容不是简单的列举命令(因为网络上大把,大家关心什么可以自己搜索),而是一贯lamecho辣么丑的风格,实战。好了各位同学坐稳了,我要发车了,哈哈。
1.2 那些需要注意的adb命令
1.2.1 “adb shell input ……”
这条命令,在测试过程中也是经常用到的,它后面可以跟tap,text,swipe,进行点击屏幕,输入文本,滑屏的操作,具体在python中使用按照命令格式执行也不会出现什么问题。但是如果我们要长按某个元素,从而实现具体功能呢?下面给出实现代码。
def long_press(dev,data,hold_time):
action='adb -s '+dev+' shell input touchscreen swipe '+'%d'%data[0][0]+' '+'%d'%(data[0][1])+' '+'%d'%data[-1][0]+' '+'%d'%(data[-1][1])+' '+hold_time
print action
pi= subprocess.Popen(action,shell=True,stdout=subprocess.PIPE)
long_press('4d0041b1be98b01f',[[540,716],[545,718]],'1000')
可以看到我定义的long_press方法,action里用到的仍然是swipe命令,大家知道swipe是滑动屏幕的操作,那么如果我们在传递滑动范围坐标的时候,设定的滑动范围非常小,那么是不是就是间接的达到了长按某一个区域的目的,然后配合一个整个命令的执行时间的参数,是不是就完美解决了长按这个动作。
我们看一看完整的adb命令:
adb -s 4d0041b1be98b01f shell input touchscreen swipe 540 716 545 718 1000
解释:-s 后跟设备号,swipe 先传移动坐标范围“540 716 545 718”,然后1000是长按的时间,1000的单位是毫秒(注意)。
大家不要以为这条命令就这样介绍结束了,还没有。按道理来说input后面的source源在swipe命令里默认就是touchscreen,所以一般我们在写这条命令时是可以省略touchscreen的,但是实际我在编写pyapp框架的时候(由于pyapp设计需要支持多台设备),拿了不同型号品牌(分辨率)的手机做适配,毕竟框架要照顾的范围要必须广要有一定的普适性。我发现,在pyapp的僚机模式下(就是一台主设备操控多台附属设备欢迎关入群”631466916“,获取最新pyswat和pyapp程序),主设备的长按操作在有些副设备上实现不成功,开始我也是在命令里省略了touchscreen。开始也想不到什么原因,因为命令来说也不复杂不存在写错的情况,毕竟有些副设备还是能正确响应动作的,后来我把shell input命令的帮助结果打印出来研究了一下(见上一篇文中有截图),在swipe命令的参数传递中说明了touchscreen是缺省,默认属性,所以正常来说我们是不用在命令中明确指定该参数值的,然而我也是瞎猫碰到死耗子,试着在命令里加入了touchscreen,最后执行结果每一台副设备在长按命令的执行上都成功了。
1.2.2 adb命令如何输入中文?
adb命令里进行输入文本输入‘adb -s 设备号shell input text 输入的内容’。在原生的adb命令里是不支持中文输入的,所以我们在测试的时候只能输入英文字符。然而实际我们在做app测试的时候避免不了需要输入中文字符的情况,这里给大家介绍一种曲线救国的办法。利用“ADBKeyBoard”输入法来进行中文的输入,通过广播的方式达到输入中文字符,具体命令:adb shell am broadcast -a ADB_INPUT_TEXT --es msg “内容”。
1.2.3 启动应用
在appium的应用中每次只能开启一个app,而如果用adb命令的话就灵活许多,输入:adb shell am start –n package名/.activity名,这里的package名和activity名和appium中配置的一致。比如我们启动计算器程序,对应的命令就是“adb shell am start -n com.android.calculator2/.Calculator”。这里要再提醒大家一点,APP的package名和activity名一定要找对特别是activity名,具体的找发大家可以参看我的《python自动化测试应用-第2篇(APP测试)--Appium初识篇》里边讲解了具体的查找方法。当然大家也是可以根据adb命令去进行查找,在pyapp测试框架中我就是根据adb命令进行名称的查找启动应用的。这里我讲解一下思路,利用命令adb shell pm list packages -3,将手机中安装的第三方app列举出来,然后通过时间比对找到新安装的app从而确定名称。其实大家只要有了思路可以在百度中查找对应的命令即可。
1.2.4 只会发短信,那么查看短信呢?不会你就out了!
网上你可能找到如何发短信,打电话的相关adb命令的介绍,其实原理也就是1.2.3中介绍的,还是启动对应的应用程序来实现。比如发短息:adb shell am start -a android.intent.action.SENDTO -d smsto:发送号码 --es sms_body 短信内容。那么如何读取一条短信内容呢?
在编写pyapp框架的过程中为了实现app的验证码自动填写功能,着实费了一番功夫。目前大部分的注册登录都是可以用动态短信验证码来进行操作的,当然app开发者本身是可以实现在收到短信后读取验证码进行自动填写,遇到没有这种功能的app我们当然也可以按照此原理去实现。由于安卓手机的所有短信都是存储在数据库中,那么我们只要找到短信的这个数据库文件,自然就可以轻松的通过python的数据库操作读取到短信内容了。'/data/data/com.android.providers.telephony/databases/mmssms.db'这个路径下“mmssms.db”文件就是保存短信内容的数据库文件,那么剩下的工作自然就是数据库的读操作了,用正则表达式匹配到验证码即可,最后通过adb的input命令写入到app中即可。这里还需要注意的是,操作“mmssms.db”文件需要root权限,所以你要想在pyapp框架里使用这个功能必须是使用root过的手机设备。
1.2.5 adb命令su权限如何使用?
什么是adb命令的su权限,举个简单的例子,比如说你要访问手机的内存/data/system路径下的文件。在cmd命令窗中你需要执行三步:
[if !supportLists]1. [endif]在cmd窗体中输入命令:adb shell回车
[if !supportLists]2. [endif]输入su回车
可以看到命令符由$变成了#符号。
[if !supportLists]3. [endif]输入cd /data/system
这样就完成了/data/system路径的访问,如果遇到那些需要权限的文件你没有执行su的话,可能就会给你返回一句Permission denied(权限拒绝)。
好了,说了这么多上面都是在cmd窗口中去分步执行的,那么在python中怎么去实现呢?如果按照之前讲解的方式在python脚本中分别执行这三条命令,肯定是不行的。因为程序执行一次adb命令,就会建立一个独立的进程,所以我们在脚本中不能按顺序执行三次adb命令,这样是达不到效果的。我们必须让一条adb命令一次完成所有的步骤的执行才对,那么我们这条命令该怎么写呢?简单暴力点,像这样:adb shell su cd data\system
肯定是不行的,不过大致意思是对的,只是具体写法上要按照正确的格式在su后面加上-c就行了。如:adb shell su –c cd “data\system”。我们看看这条命令,注意以后需要su权限的adb命令都可以这样写,-c后面跟着具体的操作命令即可。
1.2.6 uiautomatorviewer 和hierarchyviewer傻傻分不清楚?
大家在做android自动化测试时,必定会需要知道界面元素/控件的相关属性,如id,class等,这时在androidsdk的tool工具中就会用到uiautomatorviewer 和hierarchyviewer。这两个工具都可以很直观的方便大家去查找界面元素,而这样只是单纯的人工借助工具去查看,既然是要做自动化测试,必然我们要去通过代码编程去代替手工操作了。在pyapp框架中,我也是利用uiautomatorviewer来捕获app界面的从而获取对应的元素/控件。接下来我们就来看看python是如何做到的。相对来说uiautomatorviewer的实现更容易些,一条adb命令就可以了。
order='adb -s device shell uiautomator dump'
运行成功后会返回:
“UI hierchary dumped to: /storage/emulated/legacy/window_dump.xml“
结果很直观了,这个window_dump.xml里就是整个界面的布局层级信息,从中我们就可以获取到各个元素/控件的属性信息。如果利用浏览器打开xml文件大家也可以直观的看到界面的层级关系,如果大家只关心具体的元素控件,我们可以在命令后面加上—compressed,这样获取的xml就会清爽许多。
我们接着看看怎么在python中利用hierarchyviewer实现元素/控件获取,首先我们要知道要实现hierarchyviewer的元素获取我们要打开手机的View Server服务,并与其进行socket通信,从而获取到元素/控件信息。那么接下来我们将通过几条不同的adb命令来准备好与View Server进行通信的环境。
第一步:
通过“adb shell service call window 3”命令得到返回值Result: Parcel(00000000 00000001 '........')或者Result: Parcel(00000000 00000000 '........')如果是00000001表示View Server是开启的,反之我们就要开启View Server服务。
第二步:
如果View Server没有打开,我们就通过“adb shell service call window 1 i32 4939”命令打开。然后再通过第一步的命令确认是否开启了View Server。
第三步:
当我们开启了服务后,需要再将手机的4939端口映射到电脑的4939端口,这样就可以进行socket通信了。命令为“adb forward tcp:4939 tcp:4939”
以上这三步完成后,接下来我们就可以在python脚本中与View Server建立socket通信了。由于已经有服务端View Server,我们只需要用python实现客户端的socket代码即可。
import socket#导入socket模块
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#建立TCP连接
sock.connect(('127.0.0.1',4939))#连接服务端地址及端口并建立连接
sock.send('list')#发送list命令向服务端
sock.recv(1024)#接收返回结果
这里就不去讲解python的socket用法了,重点讲解一下这里的list指令。当我们建立好与View Server的通信后,就可以发送不同的指令向服务端,获取信息了,这里的list意思就是获取当前手机活动界面的信息。如下图
有了这个信息,我们就可以继续发送dump命令去获取具体某个界面的详细层级信息了。举个例子比如我们要打印出上图中第二行
“432b8608 com.miui.home/com.miui.home.launcher.Launcher”
的界面信息,在我们发送内容中应该这样写sock.send(“dump 432b8608”),获取结果如下图。由于内容会比较多,建议大家在代码中将返回值写入txt文件中,方便查看。具体的内容中每一段表示一个元素,里边详细的列举了元素的各种属性信息,如id,class,坐标等。
至此,我们了解到通过发送list,dump两个命令可以进行元素信息的获取。另外还有一个capture命令可以获取到元素在界面中的截图,这里就不再赘述了。至于到底是用uiautomatorviewer 还是hierarchyviewer去实现元素的获取,决定权就在你的手上了。
好了,有关python自动化测试应用-第11篇(APP测试)之adb命令(下篇)就写到这里。本篇着重讲解了一些非常规的adb命令的使用,尽可能的贴住适合我们做自动化测试相关的adb’命令使用,或者说是针对我在写pyapp时实现的一些比较实用的adb’命令。最后再声明本文不去列举adb命令,网上资料有很多,最后希望本篇文章能够帮助到大家。我是你们的lamecho辣么丑。
同时欢迎大家下载使用pyswat,pyapp自动化测试框架。
原创文章,转载请注明出处。
欢迎关入群”631466916“,获取最新pyswat和pyapp程序
网友评论