MonkenRunner通过HierarchyViewer定位控件的方法和建议(Appium/UIAutomator/Robotium姊妹篇)
1. 背景
在使用MonkeyRunner的时候我们经常会用到Chimchat下面的HierarchyViewer模块来获取目标控件的一些信息来辅助我们测试,但在MonkeyRunner的官网上是没有看到相应的API的描述的,上面只有以下三个类的API引用信息(http://developer.android.com/tools/help/MonkeyDevice.html)
- MonkeyDevice
- MonkeyImage
- MonkeyRunner
2.findViewById(String id)
2.1 示例
targetDevice = MonkeyRunner.waitForConnection()
'''
public ViewNode findViewById(String id)
* @param id id for the view.
* @return view with the specified ID, or {@code null} if no view found.
'''
viewer = targetDevice.getHierarchyViewer()
button = viewer.findViewById('id/title')
text = viewer.getText(button)
print text.encode('utf-8')
2.2 分析和建议
- 一旦MonkeyRunner连接上设备,会立刻获得一个MonkeyDevice的对象代表了目标测试设备,我们就是通过这个设备对象来控制设备的
- 注意这里需要填写的id的格式和UIAutomatorViewer获得ResourceId是不一样的,请看下图UIAutomatorViewer截图中ResourceId前面多出了"android:"字串:
- 这个方法返回的一个ViewNode的对象,代表目标控件,拥有大量控件相关的属性,由于篇幅问题这里不详述,往后应该会另外撰文描述它的使用。在本文里知道它代表了目标控件就行了
- 最后打印的时候需要转换成UTF-8编码的原因跟Jython默认的编码格式有关系,具体描述和Workaround请查看:http://www.haogongju.net/art/1636997
3. findViewById(String id, ViewNode rootNode)
3.1示例
'''
public ViewNode findViewById(String id, ViewNode rootNode)
* Find a view by ID, starting from the given root node
* @param id ID of the view you're looking for
* @param rootNode the ViewNode at which to begin the traversal
* @return view with the specified ID, or {@code null} if no view found. '''
iconMenuView = viewer.findViewById('id/icon_menu')
button = viewer.findViewById('id/title',iconMenuView)
print "Button Text:",text.encode('utf-8')
3.2分析
4 getAbsolutePositionOfView(ViewNode node)
4.1示例
'''
public static Point getAbsoluteCenterOfView(ViewNode node)
* Gets the absolute x/y center of the specified view node.
*
* @param node view node to find position of.
* @return absolute x/y center of the specified view node.
*/
'''
point = viewer.getAbsoluteCenterOfView(button)
print "Button Absolute Center Position:",point
4.2 分析和建议
5. getAbsoluteCenterOfView(ViewNode node)
5.1 示例
'''
public static Point getAbsoluteCenterOfView(ViewNode node)
* Gets the absolute x/y center of the specified view node.
*
* @param node view node to find position of.
* @return absolute x/y center of the specified view node.
*/
'''
point = viewer.getAbsoluteCenterOfView(button)
print "Button Absolute Center Position:",point
5.2 分析和建议
6. getFocusedWindowName()
6.1 示例
'''
public String getFocusedWindowName()
* Gets the window that currently receives the focus.
*
* @return name of the window that currently receives the focus.
'''
window = viewer.getFocusedWindowName()
print "Window Name:",window.encode('utf-8')
6.2 解析
7. visible(ViewNode node)
7.1 示例
'''
public boolean visible(ViewNode node)
* Gets the visibility of a given element.
* @param selector selector for the view.
* @return True if the element is visible.
'''
isVisible = viewer.visible(button)
print "is visible:",isVisible
就是查看下控件是否可见,没什么好解析的了。
8. 测试代码
from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice
from com.android.monkeyrunner.easy import EasyMonkeyDevice,By
from com.android.chimpchat.hierarchyviewer import HierarchyViewer
from com.android.hierarchyviewerlib.models import ViewNode, Window
from java.awt import Point #from com.android.hierarchyviewerlib.device import #Connect to the target targetDevice
targetDevice = MonkeyRunner.waitForConnection() easy_device = EasyMonkeyDevice(targetDevice) #touch a button by id would need this
targetDevice.startActivity(component="com.example.android.notepad/com.example.android.notepad.NotesList") #time.sleep(2000)
#invoke the menu options
MonkeyRunner.sleep(6)
targetDevice.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP); '''
public ViewNode findViewById(String id)
* @param id id for the view.
* @return view with the specified ID, or {@code null} if no view found.
'''
viewer = targetDevice.getHierarchyViewer()
button = viewer.findViewById('id/title')
text = viewer.getText(button)
print text.encode('utf-8') '''
public ViewNode findViewById(String id, ViewNode rootNode)
* Find a view by ID, starting from the given root node
* @param id ID of the view you're looking for
* @param rootNode the ViewNode at which to begin the traversal
* @return view with the specified ID, or {@code null} if no view found. '''
iconMenuView = viewer.findViewById('id/icon_menu')
button = viewer.findViewById('id/title',iconMenuView)
print "Button Text:",text.encode('utf-8') '''
public String getFocusedWindowName()
* Gets the window that currently receives the focus.
*
* @return name of the window that currently receives the focus.
'''
window = viewer.getFocusedWindowName()
print "Window Name:",window.encode('utf-8') '''
public static Point getAbsoluteCenterOfView(ViewNode node)
* Gets the absolute x/y center of the specified view node.
*
* @param node view node to find position of.
* @return absolute x/y center of the specified view node.
*/
'''
point = viewer.getAbsoluteCenterOfView(button)
print "Button Absolute Center Position:",point '''
public static Point getAbsolutePositionOfView(ViewNode node)
* Gets the absolute x/y position of the view node.
*
* @param node view node to find position of.
* @return point specifying the x/y position of the node.
'''
point = viewer.getAbsolutePositionOfView(button)
print "Button Absolute Position:", point '''
public boolean visible(ViewNode node)
* Gets the visibility of a given element.
* @param selector selector for the view.
* @return True if the element is visible.
'''
isVisible = viewer.visible(button)
print "is visible:",isVisible
9.附上HierarchyViewer类的源码方便参照
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.chimpchat.hierarchyviewer;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.hierarchyviewerlib.device.DeviceBridge;
import com.android.hierarchyviewerlib.device.ViewServerDevice;
import com.android.hierarchyviewerlib.models.ViewNode;
import com.android.hierarchyviewerlib.models.Window;
import org.eclipse.swt.graphics.Point;
/**
* Class for querying the view hierarchy of the device.
*/
public class HierarchyViewer {
public static final String TAG = "hierarchyviewer";
private IDevice mDevice;
/**
* Constructs the hierarchy viewer for the specified device.
*
* @param device The Android device to connect to.
*/
public HierarchyViewer(IDevice device) {
this.mDevice = device;
setupViewServer();
}
private void setupViewServer() {
DeviceBridge.setupDeviceForward(mDevice);
if (!DeviceBridge.isViewServerRunning(mDevice)) {
if (!DeviceBridge.startViewServer(mDevice)) {
// TODO: Get rid of this delay.
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
if (!DeviceBridge.startViewServer(mDevice)) {
Log.e(TAG, "Unable to debug device " + mDevice);
throw new RuntimeException("Could not connect to the view server");
}
return;
}
}
DeviceBridge.loadViewServerInfo(mDevice);
}
/**
* Find a view by id.
*
* @param id id for the view.
* @return view with the specified ID, or {@code null} if no view found.
*/
public ViewNode findViewById(String id) {
ViewNode rootNode = DeviceBridge.loadWindowData(
new Window(new ViewServerDevice(mDevice), "", 0xffffffff));
if (rootNode == null) {
throw new RuntimeException("Could not dump view");
}
return findViewById(id, rootNode);
}
/**
* Find a view by ID, starting from the given root node
* @param id ID of the view you're looking for
* @param rootNode the ViewNode at which to begin the traversal
* @return view with the specified ID, or {@code null} if no view found.
*/
public ViewNode findViewById(String id, ViewNode rootNode) {
if (rootNode.id.equals(id)) {
return rootNode;
}
for (ViewNode child : rootNode.children) {
ViewNode found = findViewById(id,child);
if (found != null) {
return found;
}
}
return null;
}
/**
* Gets the window that currently receives the focus.
*
* @return name of the window that currently receives the focus.
*/
public String getFocusedWindowName() {
int id = DeviceBridge.getFocusedWindow(mDevice);
Window[] windows = DeviceBridge.loadWindows(new ViewServerDevice(mDevice), mDevice);
for (Window w : windows) {
if (w.getHashCode() == id)
return w.getTitle();
}
return null;
}
/**
* Gets the absolute x/y position of the view node.
*
* @param node view node to find position of.
* @return point specifying the x/y position of the node.
*/
public static Point getAbsolutePositionOfView(ViewNode node) {
int x = node.left;
int y = node.top;
ViewNode p = node.parent;
while (p != null) {
x += p.left - p.scrollX;
y += p.top - p.scrollY;
p = p.parent;
}
return new Point(x, y);
}
/**
* Gets the absolute x/y center of the specified view node.
*
* @param node view node to find position of.
* @return absolute x/y center of the specified view node.
*/
public static Point getAbsoluteCenterOfView(ViewNode node) {
Point point = getAbsolutePositionOfView(node);
return new Point(
point.x + (node.width / 2), point.y + (node.height / 2));
}
/**
* Gets the visibility of a given element.
*
* @param selector selector for the view.
* @return True if the element is visible.
*/
public boolean visible(ViewNode node) {
boolean ret = (node != null)
&& node.namedProperties.containsKey("getVisibility()")
&& "VISIBLE".equalsIgnoreCase(
node.namedProperties.get("getVisibility()").value);
return ret;
}
/**
* Gets the text of a given element.
*
* @param selector selector for the view.
* @return the text of the given element.
*/
public String getText(ViewNode node) {
if (node == null) {
throw new RuntimeException("Node not found");
}
ViewNode.Property textProperty = node.namedProperties.get("text:mText");
if (textProperty == null) {
// give it another chance, ICS ViewServer returns mText
textProperty = node.namedProperties.get("mText");
if (textProperty == null) {
throw new RuntimeException("No text property on node");
}
}
return textProperty.value;
}
}
10. 参考阅读
| 作者 | 自主博客 | 微信服务号及扫描码 | CSDN |
| 天地会珠海分舵 | http://techgogogo.com | 服务号:TechGoGoGo扫描码: ![]() |
http://blog.csdn.net/zhubaitian |
MonkenRunner通过HierarchyViewer定位控件的方法和建议(Appium/UIAutomator/Robotium姊妹篇)的更多相关文章
- MonkenRunner通过HierarchyViewer定位控制的方法和建议(Appium/UIAutomator/Robotium侣)
1. 背景 正在使用MonkeyRunner当我们经常使用Chimchat下面HierarchyViewer模块获得目标控制的一些信息,以协助我们测试.但在MonkeyRunner官方的说法是没有看到 ...
- UIAutomator定位Android控件的方法
UIAutomator各种控件定位的方法. 1. 背景 使用SDK自带的NotePad应用,尝试去获得在NotesList那个Activity里的Menu Options上面的那个Add note菜单 ...
- 【转】UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
原文地址:http://blog.csdn.net/zhubaitian/article/details/39777951 在本人之前的一篇文章<<Appium基于安卓的各种FindEle ...
- UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
在本人之前的一篇文章<<Appium基于安卓的各种FindElement的控件定位方法实践和建议>>第二章节谈到Appium可以通过使用UIAutomator的方法去定位And ...
- ADF控件ID变化引发JS无法定位控件的解决方法
原文地址:ADF控件ID变化引发JS无法定位控件的解决方法作者:Nicholas JSFF定义的控件ID到了客户端时往往会改变.例如在JSFF中的一个的ID为"ot1",但是当这个 ...
- Auto.js 特殊定位控件方法 不能在ui线程执行阻塞操作,请使用setTimeout代替
本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! Auto.js 特殊定位控件方法 操作环 ...
- 转载:Robotium之Android控件定位实践和建议(Appium/UIAutomator姊妹篇)
来源于:http://blog.csdn.net/zhubaitian/article/details/39803857 1. 背景 为保持这个系列的一致性,我们继续用SDK自带的NotePad实例应 ...
- Robotium之Android控件定位实践和建议(Appium/UIAutomator姊妹篇)
本人之前以前撰文描写叙述Appium和UIAutomator框架是怎样定位Android界面上的控件的. UIAutomator定位Android控件的方法实践和建议 Appium基于安卓的各种Fin ...
- 百度地图js版定位控件
一 概述 百度地图在最新版已加入浏览器定位控件,个人认为应该是既高德地图更新了一个浏览器也能定位功能后,百度不甘落后自己简简单单,草草写了个这个功能的定位控件 GeolocationControl 这 ...
随机推荐
- Matlab Newton‘s method
定义函数 function y=f(x) y=f(x).%函数f(x)的表达式 end function z=h(x) z=h(x).%函数h(x)的表达式 end 主程序 x=X;%迭代初值 i=0 ...
- C指针决心 ------ 指针表达式
本文是自己学习所做笔记.欢迎转载.但请注明出处:http://blog.csdn.net/jesson20121020 所谓的指针表达式是指一个表达式.其结果是一个指针. 例1. int a,b; ...
- 播放视频的框架Vitamio的使用问题
曾经用过这个牛逼的框架,后来又任意搞了下.发现播放不了视频了.搞了老半天才搞好,今天又随便整了下,发现又不行了.我勒个插! 如今最终又搞出来了,发现我总是把步骤搞错或少写了些东西 总的步骤: 一:导入 ...
- boostrap-非常好用但是容易让人忽略的地方------row
row是非常好用但是却非常容易忽略的地方. 想实现内部元素相对父级的padding=0,则在父子中间加个row.如下图 列嵌套也是同样的道理 经验之谈:学会row的用法,在手机版布局的时候会很方便,否 ...
- OpenGL缓冲区
OpenGL缓冲区 颜色缓冲区 OpenGL时,先是在一个缓冲区中完毕渲染,然后再把渲染结果交换到屏幕上. 我们把这两个缓冲区称为前颜色缓冲区(屏幕)和后颜色缓冲区.在默认情况下,OpenGL命令是在 ...
- Theano学习笔记(三)——图结构
图结构(Graph Structures)这是理解Theano该基金会的内部运作. Theano编程的核心是用符号占位符把数学关系表示出来. 图结构的组成部分 如图实现了这段代码: importthe ...
- OpenWrt arp 命令发布
arp命令是用来查看mac与ip在消息路由器缓存表.这是一个基本的介绍了一下我就不说了. 但今天我的同事通过arp.可是在shell脚本就回显示没有此命令,我当时也感到非常费解. 于是乎.做了例如以下 ...
- 采用Duplicate target database在线恢复秩序oracle datagard图书馆设备
线上oracle datagard备库由于断电以及误删除从库的归档日志文件,所以导致,备库主库数据不一致,备库须要紧急恢复.以下是大概恢复过程 1,从主库上面备份控制文件[oracle@localho ...
- 修改Oracle XE Listener 占用的1521、8080端口
修改Oracle XE Listener 占用的1521.8080端口今天在帮开发人员Demon安装oracleXE时,有这么一段提示: [sql] Destination Folder: D:\ ...
- react学习笔记2--练习Demos
准备工作 # 0.react核心库 <script src="../build/react.js"></script> # 将JSX 语法转为 JavaSc ...
