这里总结如何使用 monkeyrunner
来自动化测试 android apk
应用。html
python
安装下载 python
的 msi
包,直接点击 next
,安装。java
java jdk
安装由于 android sdk
这些是基于 java jvm
,因此须要须要 java jdk
环境node
android sdk
安装使用 android sdk manager
管理工具,来安装 android sdk tools
和 android sdk platform_tools
。这里也须要安装一个版本的 sdk platform
,
截图以下:python
因为 GWF
的缘由,使用 google
的源安装 sdk
比较困难,咱们能够换成国内的源。点击这里android
windows
下配置环境变量monkeyrunner
是 android platform_tools
中提供的一个自动化测试接口工具。能够经过脚原本模拟 APP
业务流程。git
这里配置github
JAVA_HOME=[你的 Java jre 文件存放根路径] ANDROID_HOME=[你的 Android sdk 文件存放根路径] Path=%JAVA_HOME%\bin;%JAVA_HOME%\lib;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;C\python
这里这样设置,是为了能够在 dos
情形下,直接执行对应的命令,如 python
, monkeyrunner
。shell
至此,环境搭建成功。windows
MonkeyRunner
是一个测试工具,经过运行 python
脚原本模拟 Android
手机界面的点击事件来测试。通常测试步骤:api
模拟界面点击事件 --> 事件结果截图 --> 截图与正确图片比较来判断测试结果是否经过
来一段简单的 python
测试脚本:
# hello.py # coding: utf-8 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage # 链接设备 device = MonkeyRunner.waitForConnection([delay secs], [deviceid]); # 安装APP apkFilePath = "E:/myapp.apk"; device.installPackage(apkFilePath); # 启动 APP # 自行 google package 和 activity 是什么 package = "com.test.myapp"; activity = "com.test.Android.myappActivity"; runComponent = package + "/" + activity; device.startActivity(component=runComponent); # 这里通常让脚本暂停一段时间,使得APP成功启动起来 MonkeyRunner.sleep(3); # 下面开始模拟界面事件 # 1. 点击事件 device.touch(x, y, "DOWN_AND_UP"); MonkeyRunner.sleep(1); # 2. 输入事件 # 先发焦点聚焦到输入控件上,而后 type 内容 device.touch(x, y, "DOWN_AND_UP"); MonkeyRunner.sleep(1); device.type(value); MonkeyRunner.sleep(1); # 3. 模拟按键按下,如后退,home按键按下 # 这里第一个参数值的定义能够 devie.press("KEYCODE_BACK", "DOWN_AND_UP"); MonkeyRunner.sleep(1); # 4. 界面滑动 device.drag((x1, y1), (x2, y2)); MonkeyRunner.sleep(1); # 点击事件触发,界面开始变化,截屏比较 imagetobecompared = MonkeyRunner.loadImageFromFile([image file path]); screenshot = device.takeSnapshot(); if screenshot.sameAs(imagetobecompared, 0.9): print "2张图片相同"; else: print "2张图片不相同";
代码中的 KEYCODE_BACK
这样的取值,能够参考
按照上方测试流程,咱们须要作什么:
正确的截图如何获取并保存下来
设定测试模拟器分辨率,而后获取控件坐标 (x, y)
缺陷有哪些:
来点击控件是经过坐标来肯定的,这样在不一样分辨率的情形下,这个坐标是不同的,测试不一样分辨率机型要写不一样的测试脚本
图片的比对,这个不怎么准确
android sdk
下提供了一些工具来帮助咱们获取界面中控件的坐标,例如 uiautomatorviewer
, hierarchyviewer
, monitor
。
这个能够打开后,经过点击界面上的控件,来获取控件的坐标。直接在 dos
下运行命令:
uiautomatorviewer
执行后效果图:
这里能够看到 bounds
属性的值 [256, 165][320, 223]
。这个是控件的左上和右下点的坐标,能够经过这2个点计算出中心点的坐标。
获取一个控件的坐标都这么麻烦。。。
这个工具提供了一套记录用户操做界面行为的操做,例如 TOUCH
, PRESS
, TYPE
, Drag
这些操做。这个工具在 tools
或者 platform-tools
下都没有看到,不过能够经过代码来调用。
# coding: utf-8 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage from com.android.monkeyrunner.recorder import MonkeyRecorder as recorder device = MonkeyRunner.waitForConnection(3, "127.0.0.1:30054"); # 启动 recorder recorder.start(device);
启动后的截图以下:
点击界面上的控件,或者 type something
, 或者 Fling
这些操做,都会在右侧中留下操做记录,这里有点击点的坐标,
或者 type value
这些操做。
导出操做到文件中,在 py
脚本文件中,实现起来就方便了。(强烈推荐这个来记录操做流程)
目前没有发现比较方便快捷的截屏保存操做。因此在这里实现了一小段截屏脚本,使用流程:
启动模拟器,安装APP并启动咱们须要测试的APP
运行咱们的脚本 mkr console.py
,这里有个 dos
窗口
在模拟器中操做APP,若是须要截屏,在步骤2中打开的 dos
窗口中输入 save
,保存截图
附上代码:
mkr.bat
文件内容
@echo off monkeyrunner %~dp0%1
console.py
文件内容
# console.py # coding: utf-8 # 链接模拟器 ... # 这里开始根据输入的命令执行对应的操做 # save: 截屏并保存 png 图片 # quit:退出 cmdstr = raw_input(">>>"); while cmdstr != "quit": # 截图保存 if cmdstr == "save": fpng = time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png"; de.saveImage(os.path.join(pydir, "images", fpng), "png"); cmdstr = raw_input(">>>");
注:
这里运行 raw_input
命令的时候会卡主。参考下面的 Q&A
部分,问题1。
使用空间坐标来操做控件,当屏幕分辨率改变时,控件坐标天然会改变。难道咱们每一个坐标都写一个测试脚本。
这里有2种解决方式:
先固定一个屏幕分辨率,而后在新分辨率下从新计算控件坐标
使用控件 id
来操做控件
方式1,假定咱们的测试脚本是在 320 * 568
分辨率下控制控件 (120, 200)
来作点击操做。原来的代码
device.touch(120, 200, "DOWN_AND_UP");
如今须要改成
dw = device.getProperty("display.width"); dh = device.getProperty("display.height"); nx = int(120 / 320.0 * int(dw)); ny = int(200 / 320.0 * int(dh));
另一种方式是,经过控件 id
来获取控件,操做控件。对应的工具 hierarchyviewer
在 dos
窗口下输入
> hierarchyviewer
运行该命令的时候,最好先把模拟器的界面调整到你须要取控件 id
的控件。上方命令成功后,会有以下截图:
这时选中 activity
点击 Load View Hierarchy
显示以下界面:
这里看到有的控件的下方有 id/content
这样的内容,这个就是控件的 id
。
使用代码示例以下:
# coding: utf-8 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage from com.android.chimpchat.hierarchyviewer import HierarchyViewer from com.android.monkeyrunner.easy import By device = MonkeyRunner.waitForConnection(1, "127.0.0.1:30054"); hdevice = device.getHierarchyViewer(); # 经过id获取node vnode = hdevice.findViewById("id/content"); # 经过node,获取位置 point = hdevice.getAbsolutePositionOfView(vnode); pcenter = hdevice.getAbsoluteCenterOfView(vnode); # 获取node中的文本内容 txt = hdevice.getText(vnode);
# coding: utf-8 ... from com.android.monkeyrunner.easy import EasyMonkeyDevice from com.android.monkeyrunner.easy import By # 链接设备,启动APP ... easydevice = EasyMonkeyDevice(device); easydevice.touch(By.id("id/content"), MonkeyDevice.DOWN_AND_UP);
monkeyrunner
raw_input()
接收输入后不运行后面的代码这个被发现是 jpython
的一个 bug
, python
版本 jython-standalone-2.5.3.jar
。
当前你使用的 jpython
版本能够在 ${ANDROID_HOME}\tools\lib
下能够看到。
fix:
https://code.google.com/p/android/issues/detail?id=56318
adb devices
检查不出来这里是由于咱们要手动链接每天模拟器,这里须要 ip
和 port
。
从上面的截图,能够看到文件夹 TianTian
, TianTian_1
, TianTian_2
...
这里的每个文件夹内容表示一个模拟器,我这里建立了3个模拟器,因此有三个文件夹。要链接哪一个模拟器,查看对应
模拟器下的链接 ip
地址,能够查看下面内容:
<!--/TianTian.vbox--> <VirtualBox ...> <Machine ...> ... <Hardware ...> ... <Network> <Adapter ...> ... <NAT> ... <Forwarding name="AdbPort" proto="1" hostip="127.0.0.1" hostport="6555" guestip="10.0.2.15" guestport="5555"/> </NAT> </Adapter> </Network> </Hardware> </Machine> </VirtualBox>
这里看到链接地址:hostip
, hostport
在 dos
下运行命令:
adb connect [hostip]:[hostport]
链接模拟器,到此 type
下面命令就能够查询到模拟器了。
adb devices
dos
命令 chcp
的介绍和使用,点击这里
显示当前 dos
环境下的编码格式
> chcp
切换到简体中文编码格式
> chcp 936
切换到英文编码格式
> chcp 437
切换到 utf-8
编码格式
> chcp 65001
若是在 monkeyrunner
中打印内容,报以下错误:
LookupError: unknown encoding 'ms936'
这个就是编码问题,执行上面的 chcp
命令,切换咱们须要的编码。