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 这 ...
随机推荐
- Oracle 数据库 JOB 失败后解密法重试
因为官方文档上没有找到相关的说明,所以这里进行了例如以下測试,为了找到oracle数据库中 job 失败后重试时间的规律. 数据库版本号:11.2.0.3 測试说明:这里创建了一个日志表以及一个执行时 ...
- 高性能 TCP & UDP 通信框架 HP-Socket v3.2.3 正式公布
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包括服务端组件.client组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#. ...
- cocos2d 消除类游戏简单的算法 (一)
1. 游戏视频演示 2.三消游戏我的理解 上面视频中的游戏.我做了2个星期时间,仅仅能算个简单Demo,还有bug.特效也差点儿没有.感觉三消游戏主要靠磨.越磨越精品. 市场上三消游戏已经超级多了.主 ...
- Android分享到微信等社交平台教程
在Android手机app上增加分享到微信等平台的功能,使用的是第三方的开源组件,友推SDK. 集成分为下面几个步骤: 1. 在友推官网注冊,加入要集成友推sdk的 app信息,并获取appkey. ...
- 一个好用的web甘特图
前些天一直在弄web甘特图,发现网上很多web甘特图框架,但大部分是收费的.偶尔发现了向日葵甘特图 感觉不错,特此写下来一方面当做记录,另一方面也为寻找web甘特图的同学们少走一些弯路,双赢嘛~ ...
- 使用批处理给IIS添加MIME类型
原文 使用批处理给IIS添加MIME类型 @echo off set /p warn="警告:本脚本会清空全部站点原有MIME类型,输入y按回车继续,直接回车退出:" if & ...
- R语言做文本挖掘 Part5情感分析
Part5情感分析 这是本系列的最后一篇文章,该.事实上这种单一文本挖掘的每一个部分进行全部值获取水落石出细致的研究,0基础研究阶段.用R里面现成的算法,来实现自己的需求,当然还參考了众多网友的智慧结 ...
- springMVC框架建设进程
1.创建Dynamic Web Project 2.导入spring和springmvc所须要的文件 3.配置web.xml文件 3.1 监听spring上下文容器 3.2 载入spring的xml文 ...
- 【Linux】CentOS系统
版本号:CentOS release 5.7 1)查看系统版本号 cat /etc/readhat-release 2)安装软件 wget 资源链接 make make install 在线安装: ...
- mysql JDBC总结
今天复习了下jdbc操作数据库,其实通过复习,感觉对类的熟悉和方法的运用都是小事,毕竟有API都可以查得到. 关键是一些设计, 1. 比如: Class.forName("");这 ...