Android自动化测试框架新书:<<MonnkeyRunner实现原理剖析>>交流
最后更新于:2022-04-01 19:57:08
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyRunner源码分析之工作原理图
最后更新于:2022-04-01 19:57:06
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
monkey源码分析之事件注入方法变化
最后更新于:2022-04-01 19:57:04
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
Monkey源码分析之事件注入
最后更新于:2022-04-01 19:57:02
事件处理方式 | MonkeyEvent实现类 | 关键代码 | 注释 |
通过WindowManager注入事件 | MonkeyKeyEvent | injectKeyiwm.injectKeyEvent(getEvent(),false)Event | |
MonkeyTouchEvent | iwm.injectPointerEvent(me,false) | ||
MonkeyTrackballEvent | iwm.injectTrackballEvent(me,false) | ||
通过往事件设备/dev/input/event0发送命令注入事件 | MonkeyFlipEvent | FileOutputStream("/dev/input/event0") | |
通过ActvityManager的startInstrumentation方法启动一个应用 | MonkeyInstrumentationEvent | iam.startInstrumentation(cn,null, 0,args,null) | |
睡眠 | MonkeyThrottleEvent | Thread.sleep(mThrottle) | |
MonkeyWaitEvent | Thread.sleep(mWaitTime) |
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
Monkey源码分析番外篇之Android注入事件的三种方法比较
最后更新于:2022-04-01 19:56:59
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
Monkey源码分析番外篇之WindowManager注入事件如何跳出进程间安全限制
最后更新于:2022-04-01 19:56:57
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
Monkey源码分析之事件源
最后更新于:2022-04-01 19:56:55
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
Monkey源码分析之运行流程
最后更新于:2022-04-01 19:56:52
* TODO: Meta state on keys * * @return Returns the last cycle which executed. If the value == mCount, no * errors detected. */ private int runMonkeyCycles() { int eventCounter = 0; int cycleCounter = 0; boolean shouldReportAnrTraces = false; boolean shouldReportDumpsysMemInfo = false; boolean shouldAbort = false; boolean systemCrashed = false; // TO DO : The count should apply to each of the script file. while (!systemCrashed && cycleCounter < mCount) { ... MonkeyEvent ev = mEventSource.getNextEvent(); if (ev != null) { int injectCode = ev.injectEvent(mWm, mAm, mVerbose); ... } ... } .... } ~~~ 注意这里的mEventSource就是我们上面提到的事件源的接口,它屏蔽了每个事件实现类的具体细节,我们只需要告诉这个接口我们现在需要取一条事件然后执行它,该结构根据面向对象的多态原理,就会自动取事件的实现类获得对应的事件进行返回。 所以这里大家还需要对多态这个概念有所了解,特别是一些从手动测试转到自动化测试的朋友,可能之前没有接触过太多面向对象的知识。本人以前做过开发,所以还ok。这里只是做一个善意的提醒。 获得事件后下一步就是去执行相应的事件了,不同的事件会有不同的处理方式,或只是执行个命令,或调用WindowManager隐藏接口做事件注入等,这些都会在今后文章进行进一步阐述 这一篇文章就到此为止了,目的就是让大家对整一个monkey执行的流程有个初步的了解,方便理解往下的相关文章。
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyRunner源码分析之启动
最后更新于:2022-04-01 19:56:50
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyRunner源码分析之与Android设备通讯方式
最后更新于:2022-04-01 19:56:48
请求 | 是否需要和目标设备通信 | 通信方式 | 注解 |
发送adb shell命令 | |||
getSystemProperty | 是 | 发送adb shell命令 | |
installPackage | 是 | 发送adb shell命令 | 传送数据时发送adb协议请求,发送安装命令时使用adb shell命令 |
startActivity | 是 | 发送adb shell命令 | |
broadcastIntent | 是 | 发送adb shell命令 | |
instrument | 是 | 发送adb shell命令 | |
shell | 是 | 发送adb shell命令 | 命令为空,所以相当于直接执行”adb shell “ |
removePackage | 是 | 发送adb shell命令 | |
发送monkey命令 | |||
getProperty | 是 | 发送monkey命令 | |
wake | 是 | 发送monkey命令 | |
dispose | 是 | 发送monkey命令 | |
press | 是 | 发送monkey命令 | |
type | 是 | 发送monkey命令 | |
touch | 是 | 发送monkey命令 | |
drag | 是 | 发送monkey命令 | |
getViewIdList | 是 | 发送monkey命令 | |
getView | 是 | 发送monkey命令 | |
getViews | 是 | 发送monkey命令 | |
getRootView | 是 | 发送monkey命令 | |
发送adb协议请求 | |||
takeSnapshot | 是 | 发送adb协议请求 | |
reboot | 是 | 发送adb协议命令 | |
installPackage | 是 | 发送adb协议请求 | 相当于直接发送adb命令行命令’adb push’ |
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyRunner源码分析之-谁动了我的截图?
最后更新于:2022-04-01 19:56:45
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
adb概览及协议参考
最后更新于:2022-04-01 19:56:43
命令 | 解释 |
host:version |
|
host:kill | 停止server |
host:devices |
|
host:track-devies |
|
host:emulator:<port> |
|
host:transport:<serial-number> | 连接指定serial-number的设备或者模拟器 |
host:transport-usb | 连接usb上的设备,如果usb上有不止一个设备,会失败。 |
host:transport-local | 通过tcp方式连接模拟器,如果有多个模拟器在运行,会失败。 |
host:transport-any | 连接usb设备或者模拟器都可以,但是如果有超过一个设备或模拟器,会失败。 |
host-serial:<serial-number>:<request> host-usb:<request> host-local:<request> | 向指定的设备发送特定的请求。同样如果存在多个设备的冲突,会失败。 |
host:<request> | 向当前连接的设备发送请求 |
<host-prefix>:get-serialno | 获取设备的serial-number |
<host-prefix>:get-state | 获取设备状态 |
<host-prefix>:forward:<local>;<remote> |
|
命令 | 解释 |
shell:command arg1 arg2 ... | 在设备上执行命令行操作 |
shell: | 参见commandline.c中的interactive_shell() |
remount: | 以读/写模式加载设备的文件系统 |
dev:<path> | 为client打开设备上的特定路径,用于读写问题。有可能由于权限问题而失败。 |
tcp:<port> | 尝试从设备连接本主机的某个tcp端口 |
tcp:<port>:<server-name> | 尝试从设备连接特定主机名的某个tcp端口 |
local:<path> | 尝试连接设备上的特定路径,路径是UNIX域名形式 |
localreserved:<path> localabstract:<path> localfilesystem:<path> | 尝试连接设备上的特定路径。 |
log:<name> | 打开设备上的特定日志文件,以便读取日志 |
framebuffer: | 尝试获取framebuffer的快照。即涉笔的屏幕快照 |
dns:<server-name> | 由serer执行来解析特定设备名 |
recover:<size> | 更新设备的恢复镜像 |
jdwp:<pid> | 连接特定VM进程上面的JDWP线程 |
track-jdwp |
|
sync: | 同步设备和主机上的文件 |
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
EasyMonkeyDevice vs MonkeyDevice&HierarchyViewer API Mapping Matrix
最后更新于:2022-04-01 19:56:41
Return | EasyMonkeyDevice | Demo | Comment
|
| EasyMonkeyDevice( MonkeyDevice device) Use Monkey device to construct an EasyMonkeyDevice object, note that it would instantiate a HierarchyViewer member by device within this constructor |
device = MonkeyRunner.waitForConnection()
eDevice=EasyMonkeyDevice(device) | Constructor |
Void | touch(By selector, TouchPressType type) Sends a touch event specified by ‘type’ to the screen location specified by ‘by’ | 触摸点击主窗口: #Step 1: try touching on the first note eDevice.touch(By.id('id/text1'), MonkeyDevice.DOWN_AND_UP) 触摸弹出框或Menu Options会失败: MonkeyRunner.sleep(2) print 'Show Menu Options' device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP);
MonkeyRunner.sleep(3) print 'Press on the menu entry of \ \"Add note\"' eDevice.touch(By.id('id/title'), MonkeyDevice.DOWN)
| 参数By实际上 只有By.ID,从 其源码可以看 出来; type参数跟 MonkeyDevice 一样就那几个 DOWN/UP之类的
根据个人实践 和网上评论, 对系统菜单和 弹出框的支持 有问题 |
Void | type(By selector, String text) Types a string into the specified object |
#Step 5: setText eDevice.type(By.id(noteId), 'New') |
|
Boolean | exists(By selector) Checks if the specified object exists. |
#Step3: is note EditText exist? noteId = 'id/note' if True == eDevice.exists(By.id(noteId)): print 'Note exist' else: print 'Note not found!' exit(2) |
|
Boolean | visible(By selector) Checks if the specified object is visible. |
#Step4: is note EditText visible? if True == eDevice.visible(By.id(noteId)): print 'Note is visible' else: print 'Note is invisible' exit(3) |
|
String | getText(By selector) Obtain the text in the selected input box. |
#Step 4: getText text = eDevice.getText(By.id(noteId)) print 'Note text:',text.encode('utf-8') |
|
String | getFocusedWindowId() Gets the id of the focused window. returns = "The symbolic id of the focused window or None." |
#Step 2: Get the window ID winId = 'com.example.android.notepad/\ com.example.android.notepad.NoteEditor' #Need to sleep a while till ready MonkeyRunner.sleep(3) winId = eDevice.getFocusedWindowId() if(winId == winId): print "Edit Note WinId is:",\ winId.encode('utf-8') else: print "Failed" exit(1) | 结果跟 HierarchyViewer 的 getFocusedWin dowName 返回值一模 一样,所以 猜想WindowID 和WindowName 是同一回事 |
PyTuple | locate(By selector) Locates the coordinates of the selected object returns = "Tuple containing (x,y,w,h) location and size.") |
#Step 6: locate locate = eDevice.locate(By.id(noteId)) print 'Location(x,y,w,h) is:',locate |
|
EasyMonkeyDevice API vs MonkeyDevice API |
| |
MonkeyDevice | EasyMonkeyDevice | Comment
|
Void broadcastIntent (string uri, string action, string data, string mimetype, iterable categories dictionary extras, component component, iterable flags) Broadcasts an Intent to this device, as if the Intent were coming from an application. |
|
|
Void drag (tuple start, tuple end, float duration, integer steps) Simulates a drag gesture (touch, hold, and move) on this device's screen. |
|
|
ObjectgetProperty (string key) Given the name of a system environment variable, returns its value for this device. The available variable names are listed in the detailed description of this method. |
|
|
ObjectgetSystemProperty (string key) . The API equivalent of adb shell getprop <key>. This is provided for use by platform developers. |
|
|
Void installPackage (string path) Installs the Android application or test package contained in packageFile onto this device. If the application or test package is already installed, it is replaced. |
|
|
Dictionaryinstrument (string className, dictionary args) Runs the specified component under Android instrumentation, and returns the results in a dictionary whose exact format is dictated by the component being run. The component must already be present on this device. |
|
|
Void press (string name, dictionary type) Sends the key event specified by type to the key specified by keycode. |
|
|
Void reboot (string into) Reboots this device into the bootloader specified by bootloadType. |
|
|
Void removePackage (string package) Deletes the specified package from this device, including its data and cache. |
|
|
Objectshell (string cmd) Executes an adb shell command and returns the result, if any. |
|
|
Void startActivity (string uri, string action, string data, string mimetype, iterable categories dictionary extras, component component, flags) Starts an Activity on this device by sending an Intent constructed from the supplied arguments. |
|
|
Captures the entire screen buffer of this device, yielding a MonkeyImage object containing a screen capture of the current display. |
|
|
Void touch (integer x, integer y, integer type) Sends a touch event specified by type to the screen location specified by x and y. | Void touch(By selector, TouchPressType type) Sends a touch event specified by ‘type’ to the screen location specified by ‘by’ | MonkeyDevice通过坐标点touch; EasyMonkeyDevice通过控件ID去touch |
Void type (string message) Sends the characters contained in message to this device, as if they had been typed on the device's keyboard. This is equivalent to calling press() for each keycode in message using the key event type DOWN_AND_UP. | Void type(By selector, String text) Types a string into the specified object | MonkeyDevice往当前focused地方输入; EasyMonkeyDevice往由ID指定控件输入 |
Void wake () Wakes the screen of this device. |
|
|
HierarchyViewer getHierarchyViewer() Get the HierarchyViewer object for the device. |
|
|
PyListgetPropertyList() Retrieve the properties that can be queried |
|
|
PyListgetViewIdList() Retrieve the view ids for the current application |
|
|
MonkeyViewgetViewById(String id) doc = "Obtains the view with the specified id.", args = {"id"}, argDocs = {"The id of the view to retrieve."}, returns = "The view object with the specified id." |
|
|
MonkeyViewgetViewByAccessibilityIds(String WinId, String accessId) args = {"windowId", "accessibility id"} argDocs = {"The window id of the view to retrieve.", "The accessibility id of the view to retrieve."}, returns = "The view object with the specified id.") |
|
|
MonkeyViewgetRootView() Obtains current root view |
|
|
PyListgetViewsByText(String text) Obtains a list of views that contain the specified text.", args = {"text"}, returns = "A list of view objects that contain the specified text.") |
|
|
EasyMonkeyDevice Standalone API |
|
EasyMonkeDevice | Comment
|
boolean exists(By selector) Checks if the specified object exists. |
|
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyImage API 实践全记录
最后更新于:2022-04-01 19:56:39
Return Type | Methods | Comment |
string | convertToBytes (string format) Converts the current image to a particular format and returns it as a string that you can then access as an iterable of binary bytes. |
|
tuple | getRawPixel (integer x, integer y) Returns the single pixel at the image location (x,y), as an a tuple of integer, in the form (a,r,g,b). |
|
integer | getRawPixelInt (integer x, integer y) Returns the single pixel at the image location (x,y), as a 32-bit integer. |
|
getSubImage (tuple rect) Creates a new |
| |
boolean | sameAs ( Compares this |
|
void | writeToFile (string path, string format) Writes the current image to the file specified by |
|
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyDevcie API 实践全记录
最后更新于:2022-04-01 19:56:36
Return Type | Methods | Comment |
void | broadcastIntent (string uri, string action, string data, string mimetype, iterable categories dictionary extras, component component, iterable flags) Broadcasts an Intent to this device, as if the Intent were coming from an application. |
|
void | drag (tuple start, tuple end, float duration, integer steps) Simulates a drag gesture (touch, hold, and move) on this device's screen. |
|
object | getProperty (string key) Given the name of a system environment variable, returns its value for this device. The available variable names are listed in the detailed description of this method. |
|
object | getSystemProperty (string key) . The API equivalent of adb shell getprop <key>. This is provided for use by platform developers. |
|
void | installPackage (string path) Installs the Android application or test package contained in packageFile onto this device. If the application or test package is already installed, it is replaced. | Obsolete,返回值是Boolean |
dictionary | instrument (string className, dictionary args) Runs the specified component under Android instrumentation, and returns the results in a dictionary whose exact format is dictated by the component being run. The component must already be present on this device. |
|
void | press (string name, dictionary type) Sends the key event specified by type to the key specified by keycode. |
|
void | reboot (string into) Reboots this device into the bootloader specified by bootloadType. |
|
void | removePackage (string package) Deletes the specified package from this device, including its data and cache. | Obsolete,返回值是Boolean |
object | shell (string cmd) Executes an adb shell command and returns the result, if any. |
|
void | startActivity (string uri, string action, string data, string mimetype, iterable categories dictionary extras, component component, flags) Starts an Activity on this device by sending an Intent constructed from the supplied arguments. |
|
Captures the entire screen buffer of this device, yielding a MonkeyImage object containing a screen capture of the current display. |
| |
void | touch (integer x, integer y, integer type) Sends a touch event specified by type to the screen location specified by x and y. |
|
void | type (string message) Sends the characters contained in message to this device, as if they had been typed on the device's keyboard. This is equivalent to callingpress() for each keycode in message using the key event type DOWN_AND_UP. |
|
void | wake () Wakes the screen of this device. |
|
Return Type | Methods | Comment |
HierarchyViewer | getHierarchyViewer(PyObject args[], String kws[]) 获取一个HierarchyViewer对象 | |
PyList | getPropertyList(PyObject args[], String kws[]) | 取得所有的property属性键值 |
PyList | getViewIdList(PyObject args[], String kws[]) | Failed |
MonkeyView | getViewById(PyObject args[], String kws[]) | Failed |
MonkeyView | getViewByAccessibilityIds(PyObject args[], String kws[]) | Failed |
MonkeyView | getRootView(PyObject args[], String kws[]) | Failed |
PyList | getViewsByText(PyObject args[], String kws[]) | Failed |
Property Group | Property | Description | Notes |
build | board | Code name for the device's system board | See Build |
brand | The carrier or provider for which the OS is customized. |
| |
device | The device design name. |
| |
fingerprint | A unique identifier for the currently-running build. |
| |
host |
|
| |
ID | A changelist number or label. |
| |
model | The end-user-visible name for the device. |
| |
product | The overall product name. |
| |
tags | Comma-separated tags that describe the build, such as "unsigned" and "debug". |
| |
type | The build type, such as "user" or "eng". |
| |
user |
|
| |
CPU_ABI | The name of the native code instruction set, in the form CPU type plus ABI convention. |
| |
manufacturer | The product/hardware manufacturer. |
| |
version.incremental | The internal code used by the source control system to represent this version of the software. |
| |
version.release | The user-visible name of this version of the software. |
| |
version.sdk | The user-visible SDK version associated with this version of the OS. |
| |
version.codename | The current development codename, or "REL" if this version of the software has been released. |
| |
display | width | The device's display width in pixels. | SeeDisplayMetricsfor details. |
height | The device's display height in pixels. |
| |
density | The logical density of the display. This is a factor that scales DIP (Density-Independent Pixel) units to the device's resolution. DIP is adjusted so that 1 DIP is equivalent to one pixel on a 160 pixel-per-inch display. For example, on a 160-dpi screen, density = 1.0, while on a 120-dpi screen, density = .75. The value does not exactly follow the real screen size, but is adjusted to conform to large changes in the display DPI. See density for more details. |
| |
am.current | package | The Android package name of the currently running package. | The am.currentkeys return information about the currently-running Activity. |
action | The current activity's action. This has the same format as the name attribute of the action element in a package manifest. |
| |
comp.class | The class name of the component that started the current Activity. See comp.package for more details. |
| |
comp.package | The package name of the component that started the current Activity. A component is specified by a package name and the name of class that the package contains. |
| |
data | The data (if any) contained in the Intent that started the current Activity. |
| |
categories | The categories specified by the Intent that started the current Activity. |
| |
clock | realtime | The number of milliseconds since the device rebooted, including deep-sleep time. | SeeSystemClock for more information. |
Type | Constants | Notes | Comment |
int(官网是string,下同) | Use this with the type argument of press() or touch() to send a DOWN event. |
| |
int | Use this with the type argument of press() or touch() to send an UP event. |
| |
int | Use this with the type argument of press() or touch() to send a DOWN event immediately followed by an UP event. |
| |
int | MOVE | TBD | 官网没有列出来 |
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkenRunner通过HierarchyViewer定位控件的方法和建议(Appium/UIAutomator/Robotium姊妹篇)
最后更新于:2022-04-01 19:56:34
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyRunner在Windows下的Eclipse开发环境搭建步骤(兼解决网上Jython配置出错的问题)
最后更新于:2022-04-01 19:56:32
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |
MonkeyRunner创建一个Note的实例
最后更新于:2022-04-01 19:56:29
前言
最后更新于:2022-04-01 19:56:27