MonkenRunner通过HierarchyViewer定位控制的方法和建议(Appium/UIAutomator/Robotium侣)
1. 背景
正在使用MonkeyRunner当我们经常使用Chimchat下面HierarchyViewer模块获得目标控制的一些信息,以协助我们测试。但在MonkeyRunner官方的说法是没有看到相应的API叙事描述,上面只有三个班API(http://developer.android.com/tools/help/MonkeyDevice.html)
- MonkeyDevice
- MonkeyImage
- MonkeyRunner
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFpdGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
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 分析和建议
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFpdGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
DecorView浅析》)左上角坐标到目标控件的的偏移坐标”,仅仅是这个最上层的DecorView的坐标一般都是从(0,0)開始而已。例如以下图我觉得最上面的那个FrameLayout就代表了DecorView,或者说整个窗口
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFpdGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
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 解析
事实上就是获得当前打开的窗体的packageName/activityName,输出与HierarchyViewer工具检測到的信息一致,所以猜想其用到相同的方法。
输出:
HierarchyViewer监控信息:
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. 參考阅读
- Robotium之Android控件定位实践和建议(Appium/UIAutomator姊妹篇)
- UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
- Appium基于安卓的各种FindElement的控件定位方法实践和建议
作者 |
自主博客 |
微信 |
CSDN |
天地会珠海分舵 |
服务号:TechGoGoGo 扫描码:
tp=webp" alt="" style="max-width:100%; margin:0px; padding:0px; height:auto!important; word-wrap:break-word!important; width:auto!important; visibility:visible!important"> |
http://blog.csdn.net/zhubaitian |
版权声明:本文博客原创文章,博客,未经同意,不得转载。
MonkenRunner通过HierarchyViewer定位控制的方法和建议(Appium/UIAutomator/Robotium侣)的更多相关文章
- MonkenRunner通过HierarchyViewer定位控件的方法和建议(Appium/UIAutomator/Robotium姊妹篇)
1. 背景 在使用MonkeyRunner的时候我们经常会用到Chimchat下面的HierarchyViewer模块来获取目标控件的一些信息来辅助我们测试,但在MonkeyRunner的官网上是没有 ...
- Robotium之Android控件定位实践和建议(Appium/UIAutomator姊妹篇)
本人之前以前撰文描写叙述Appium和UIAutomator框架是怎样定位Android界面上的控件的. UIAutomator定位Android控件的方法实践和建议 Appium基于安卓的各种Fin ...
- 转载:Robotium之Android控件定位实践和建议(Appium/UIAutomator姊妹篇)
来源于:http://blog.csdn.net/zhubaitian/article/details/39803857 1. 背景 为保持这个系列的一致性,我们继续用SDK自带的NotePad实例应 ...
- 学习linux/unix编程方法的建议(转)
假设你是计算机科班出身,计算机系的基本课程如数据结构.操作系统.体系结构.编译原理.计算机网络你全修过 我想大概可以分为4个阶段,水平从低到高从安装使用=>linux常用命令=>linux ...
- 重新 java 对象的 equals 和 hashCode 方法的建议和示例代码
equals 方法 equals 方法需要满足的规范: 自反性: 对于任意非空引用 x, x.equals(x) 应该返回 true; 对称性: 对于任意引用, 当且仅当 x.equals(y) == ...
- 学习linux/unix编程方法的建议,学习Linux的四个步骤(转)
解答:学习Linux的四个步骤假设你是计算机科班出身,计算机系的基本课程如数据结构.操作系统.体系结构.编译原理.计算机网络你全修过我想大概可以分为4个阶段,水平从低到高从安装使用=>linux ...
- 编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议47~51)
建议47:在equals中使用getClass进行类型判断 本节我们继续讨论覆写equals的问题,这次我们编写一个员工Employee类继承Person类,这很正常,员工也是人嘛,而且在JavaBe ...
- 【转】UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
原文地址:http://blog.csdn.net/zhubaitian/article/details/39777951 在本人之前的一篇文章<<Appium基于安卓的各种FindEle ...
- UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
在本人之前的一篇文章<<Appium基于安卓的各种FindElement的控件定位方法实践和建议>>第二章节谈到Appium可以通过使用UIAutomator的方法去定位And ...
随机推荐
- spring MVC 下载文件(转)
springle MVC中如何下载文件呢? 比struts2 下载文件简单得多 先看例子: @ResponseBody @RequestMapping(value = "/download& ...
- hdu1151 Air Raid,DAG图的最小路径覆盖
点击打开链接 有向无环图的最小路径覆盖 = 顶点数- 最大匹配 #include <queue> #include <cstdio> #include <cstring& ...
- java 线程 ProducerAndConsumer
package j2se.thread.demo; /** * <p>Project:J2SE 的基础知识</p> * <p>Tile:多线程模拟 生产者 和 消费 ...
- SocketAsyncEventArgs使用解说
原文:SocketAsyncEventArgs使用解说 如果在.NET下写过网络通讯的同学应该感觉不陌生了,有很多刚入门的同学很多都认为这东西可以大大提高处理效能还有就是使用上很不适应.其实使用之前最 ...
- httl开源JAVA模板引擎,动态HTML页面输出
HTTL(Hyper-Text Template Language)是一个适用于HTML输出的开源JAVA模板引擎,适用于动态HTML页面输出,可用于替代JSP页面,它的指令类似于Velocity. ...
- mongodb常用操作语句
mongodb常用操作语句 A:创建数据表 db.createCollection(name, {capped: <Boolean>, autoIndexId: <Boolean&g ...
- A Game of Thrones(1) - Bran
The morning had dawned clear and cold, with a crispness(易碎:清新) that hinted(暗示:示意) at the end of summ ...
- iOS UITableView的Section Footer加入button
郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠.支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 在处理UI ...
- SSH是什么?Linux如何修改SSH端口号?
通过SSH连接可以远程管理Linux等设备,默认linuxssh端口是22端口,如何修改SSH默认端口,如何增加SSH端口呢?,下面小编给大家演示一下 工具/原料 Xshell putty 等 ...
- 《深入浅出 Java Concurrency》—锁紧机构(一)Lock与ReentrantLock
转会:http://www.blogjava.net/xylz/archive/2010/07/05/325274.html 前面的章节主要谈谈原子操作,至于与原子操作一些相关的问题或者说陷阱就放到最 ...