Skip to content

Commit d342282

Browse files
chenqichenqi
authored andcommitted
Add monkeyrunner doc
1 parent 9698ca4 commit d342282

File tree

2 files changed

+92
-35
lines changed

2 files changed

+92
-35
lines changed

MonkeyRunner/README.md

Lines changed: 91 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,92 @@
1-
### uiparser ( MonkeyRunner is DEAD )
1+
# MonkeyRunner is DEAD
22

3-
Setup
4-
> export ANDROID_HOME="/Users/chenqi/Library/Android/sdk"
3+
## UI Automator
54

6-
Run
7-
> $ANDROID_HOME/tools/bin/monkeyrunner uiparser.py
5+
https://developer.android.com/training/testing/ui-automator
86

9-
### MonkeyRunner
10-
https://developer.android.google.cn/studio/test/monkeyrunner
7+
Android 平台所有自动化测试框架的底层实现都依赖官方提供的 UI Automator 测试框架,适用于跨系统和已安装应用程序的跨应用程序功能UI测试。主要功能包括三部分:
118

12-
#### MonkeyDevce.shell()
13-
>object shell (string cmd)
14-
Executes an `adb` shell command and returns the result, if any.
9+
+ UI Automator Viewer 检查布局层次结构的查看器。
10+
+ UiDevice 设备状态信息并在目标设备上执行操作的API。
11+
+ UI Automator API 支持跨应用程序UI测试的API。
12+
13+
## UI Automator Viewer
14+
15+
PC 端 GUI 工具,扫描和分析 Android 设备上当前显示的 UI 组件。展示 UI 布局层次结构,查看设备上当前对用户可见的 UI 组件的属性。从名称可以看出,它是 UI Automator 的只读功能部分,即只能查看 UI 组件的树形结构和属性,不能操作控制 UI 组件。
16+
17+
`uiautomatorviewer` 位于 `<android-sdk>/tools/bin` 目录。启动入口是一个bash文件,实际调用 `<android-sdk>/tools/lib` 目录的 `uiautomatorviewer-26.0.0-dev.jar` 。 GUI 基于 Eclipse + SWT 实现,使用 Gradle 构建。系列工具源码在 `https://android.googlesource.com/platform/tools/swt/` ,依赖 `https://android.googlesource.com/platform/tools/base/` 。活跃分支: `mirror-goog-studio-master-dev` 。该仓库还包含 `chimpchat, ddms, hierarchyviewer2, monkeyrunner, swtmenubar, traceview` 这些工具。
18+
19+
其内部实现基于 `adb shell uiautomator dump` 。从源码仓库提交记录看,主要功能开发的活跃时间是 2014-2015,2016之后已经很少更新维护。那个年代的 Android 开发主要使用 Eclipse , 所以基于 SWT 实现多平台 PC GUI ,在当时合理。
20+
21+
该工具实际使用运行不稳定,极易报错,常见:`Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn't exist!`
22+
23+
错误原因通常是:
24+
25+
+ adb 连接通道不稳定。
26+
+ 机型兼容性问题,权限问题。
27+
+ 当前手机应用程序界面处于动态,例如播放视频,动画。并且10秒超时时间仍未进入静态。
28+
29+
分析源码可知,错误都源于 `Android Framework uiautomator`
30+
31+
## MonkeyRunner
1532

16-
等同于调用`adb shell`命令。
17-
https://developer.android.google.cn/studio/command-line/adb#shellcommands
33+
https://developer.android.com/studio/test/monkeyrunner
34+
35+
官方提供的另外一个工具,封装 uiautomator API,供 Python 脚本调用,也可注入 java 扩展插件。相比 `uiautomatorviewer``uiautomator` 命令行工具,可编程扩展性更佳。
36+
37+
MonkeyRunner 使用了比较冷门的 Jython 实现。我参照官方文档实现了一个Demo。详见 [uiparser.py](https://github.com/9468305/python-script/blob/master/monkeyrunner/uiparser.py)
38+
39+
### 1. 启动运行入口
40+
41+
> monkeyrunner -plugin <plugin_jar> <program_filename> <program_options>
42+
43+
monkeyrunner 是一个bash文件,位于 `<android-sdk>/tools/bin` ,启动调用 `<android-sdk>/tools/lib/monkeyrunner-26.0.0-dev.jar`
44+
45+
```bash
46+
export ANDROID_HOME="~/Library/Android/sdk"
47+
$ANDROID_HOME/tools/bin/monkeyrunner uiparser.py
48+
```
49+
50+
### 2. 主要方法
1851

1952
#### MonkeyDevice.getProperty()
20-
> object getProperty (string key)
21-
Given the name of a system environment variable, returns its value for this device.
2253

23-
获取设备系统环境变量。
24-
等同于调用`adb shell getprop <keyword>`
25-
不同厂商的设备,key可能不同。
26-
使用`adb shell getprop`,显示所有系统环境变量的key字符串
54+
等同于调用 `adb shell getprop <keyword>` 。获取设备系统环境变量。
55+
不同厂商的设备,key可能不同。针对具体测试机型,可使用 `adb shell getprop` ,显示所有系统环境变量的key字符串。
2756

28-
### adb
57+
#### MonkeyDevce.shell()
58+
59+
等同于调用`adb shell`命令。
60+
61+
### 3. 缺陷
62+
63+
MonkeyRunner 基于 Jython version 2.5.3 。看上去结合了Java和Python的优势,实际对于Java和Python编程都不友好。
64+
65+
+ Jython 2.5.3 过时,主流的Python 3.x和2.7的很多语法和库无法使用。
66+
+ 使用vscode等编辑器编码时,缺少智能提示和自动补全。编辑器和pylint无法识别导入的库, 例如 `from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage`
67+
+ Jython 似乎不能像常规的python程序一样引用外部库。实测只能使用 MonkeyRunner 内置的 `os, sys, subprocess` 等库。
68+
+ Java extend plugin 能做的事情较少。
69+
70+
MonkeyRunner 实际仍然是使用 `adb shell` 和其中的 `uiautomator` 命令获取UI组件状态和属性。所以它跟 `UI Automator Viewer` 一样受限于 `uiautomator` 本身的缺陷,导致运行不稳定。
71+
72+
## adb shell uiautomator
73+
74+
**adb**
2975
https://developer.android.google.cn/studio/command-line/adb
3076

31-
#### adb shell am
77+
**adb shell am**
3278
https://developer.android.google.cn/studio/command-line/adb#am
3379
使用 Activity Manager (am) 工具发出命令以执行各种系统操作,如启动 Activity、强行停止进程、广播 intent、修改设备屏幕属性及其他操作。
3480

35-
#### adb shell pm
81+
**adb shell pm**
3682
https://developer.android.google.cn/studio/command-line/adb#pm
3783
使用软件包管理器 Package Manager (pm) 工具发出命令,安装,卸载,查询安装包。
3884

39-
#### adb shell uiautomator
40-
获取当前界面的层级结构XML信息。
41-
```
42-
adb shell uiautomator dump /sdcard/uiparser/ui.xml
43-
adb pull /sdcard/uiparser/ui.xml ./ui.xml
44-
```
45-
Usage:
46-
```
85+
**adb shell uiatomator**
86+
官网相关页面已被删除,仅能从搜索引擎历史快照中找到。猜测可能近期会有变更,或者官方建议不再使用。
87+
通过执行命令可以查看使用方法和参数。
88+
89+
```bash
4790
Usage: uiautomator <subcommand> [options]
4891

4992
Available subcommands:
@@ -80,10 +123,19 @@ dump: creates an XML dump of current UI hierarchy
80123
events: prints out accessibility events until terminated
81124
```
82125
83-
### Bug
84-
[DumpCommand.java](https://android.googlesource.com/platform/frameworks/testing/+/master/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java)
126+
### uiautomator 缺陷
127+
128+
运行耗时长,失败率高,频繁报错。
129+
`ERROR: could not get idle state.` 通常表示当前UI处于动态渲染刷新期间,例如正在播放视频,动画。在10秒超时时间内仍未进入静态。因为此时 UI 树的节点对象快速变化中,不能稳定获取。
130+
131+
### uiautomator 源码
132+
133+
关键代码 `uiAutomation.waitForIdle(1000, 1000 * 10);` 即单次超时等待1秒,最长超时等待10秒。超时抛出异常。
85134
86-
`uiAutomation.waitForIdle(1000, 1000 * 10);`
135+
`DumpCommand.java`
136+
> https://android.googlesource.com/platform/frameworks/testing/+/master/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
137+
138+
TODO: choose right branch
87139
88140
```Java
89141
// It appears that the bridge needs time to be ready. Making calls to the
@@ -113,7 +165,8 @@ System.out.println(
113165
String.format("UI hierchary dumped to: %s", dumpFile.getAbsolutePath()));
114166
```
115167
116-
[UiAutomation.java](https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/app/UiAutomation.java)
168+
`UiAutomation.java`
169+
> https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/app/UiAutomation.java
117170
118171
```Java
119172
/**
@@ -163,4 +216,8 @@ public void waitForIdle(long idleTimeoutMillis, long globalTimeoutMillis)
163216
}
164217
}
165218
}
166-
```
219+
```
220+
221+
## hierarchyviewer2
222+
223+
TODO

MonkeyRunner/uiparser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,6 @@ def uiparser():
6969

7070

7171
if __name__ == "__main__":
72-
# MonkeyRunner Jython version is 2.5.3 (Stupid!)
72+
# MonkeyRunner Jython version is 2.5.3 (Outdated!)
7373
logging.info(sys.version)
7474
uiparser()

0 commit comments

Comments
 (0)