【转】UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
原文地址:http://blog.csdn.net/zhubaitian/article/details/39777951
在本人之前的一篇文章<<Appium基于安卓的各种FindElement的控件定位方法实践和建议>>第二章节谈到Appium可以通过使用UIAutomator的方法去定位Android界面上的控件,当时只是一笔带过举了个例子。如该文给自己的承诺,今天特撰写此文以描述UIAutomator各种控件定位的方法,以作为前文的姊妹篇互通有无。
1. 背景
为了和前文达成一致,这次的实践对象同样也是使用SDK自带的NotePad应用,同样是尝试去获得在NotesList那个Activity里的Menu Options上面的那个Add note菜单选项。以下是UIAutomatorViewer对界面的一个截图.
但有一个例外的地方是下文的”通过伪xpath方法定位控件“章节实例需要使用到的是NoteEditor这个activity里面的Menu options,因为需要演示通过子控件获得父控件然后得到兄弟控件的功能,UIAutomatorViewer截图如下。
2. 通过文本信息定位
2.1 UISelector.text方法
- addNote = new UiObject(new UiSelector().text("Add note"));
- assertEquals(addNote.getText(),"Add note");
该方法通过直接查找当前界面上所有的控件来比较每个控件的text属性是否如预期值来定位控件,挺好理解的,所以就没有必要细说了。
2.2. UISelector.textContains方法
- addNote = new UiObject(new UiSelector().textContains("Add"));
- assertEquals(addNote.getText(),"Add note");
此方法跟以上方法类似,但是不需要输入控件的全部text信息。
2.3 UISelector.textStartsWith方法
- addNote = new UiObject(new UiSelector().textStartsWith("Add"));
- assertEquals(addNote.getText(),"Add note");
顾名思义,通过判断一个控件的text的开始是否和预期的字串相吻合来获得控件,其实个人觉得这个方法存在的必要性不强,因为它的功能完全可以用上面的方法或者下面的正则表达式的方法取代。况且既然你提供了textStartsWith方法,为什么你不提供个textEndWith的方法呢!
2.4 UISelector.textMatches方法
- addNote = new UiObject(new UiSelector().textMatches("^Add.*"));
- assertEquals(addNote.getText(),"Add note");
这个方法是通过正则表达式的方式来比较控件的text来定位控件,这里有意思的是用户使用的正则表达式是有限制的,请看该方法的官方描述:”Set the search criteria to match the visible text displayed for a widget (for example, the text label to launch an app). The text for the widget must match exactly with the string in your input argument“。第一句我们不用管它,关键是第二句,翻译过来就是”目标控件的text(的所有内容)必须和我们输入的正则表达式完全匹配“。什么意思呢?意思就是你不能像往常的正则表达式那样通过比较text的部分吻合来获得控件。以下面代码为例子:
- addNote = new UiObject(new UiSelector().textMatches("^Add"));
- assertEquals(addNote.getText(),"Add note");
正常来说这个正则表达式是没有问题的,它的意思就是想要“获取以Add开头的text的控件,至于Add字串口面是什么值,没有必要去管它”。但是按照我们上面的官方描述,这样子是不行的,你必须要把正则表达式补充完整以使得正而表达式和控件的text完全进行匹配,至于你用什么通配符或者字串就完全按照正则表达式的语法了。
3 通过控件的ClassName定位
通过这种方法定位控件存在的一个问题是很容易发生重复,所以一般都是先用这种方法去narrow down目标控件,然后再去添加其他如text判断等条件进行控件定位。
3.1 UISelector.className方法
- addNote = new UiObject(new UiSelector().className("android.widget.TextView").text("Add note"));
- assertEquals(addNote.getText(),"Add note");
实例中首先通过ClassName找到所有的TextView控件,然后再在这些TextView控件查找text是”Add note“的控件。
3.2 UISelector.classNameMatches方法
- addNote = new UiObject(new UiSelector().classNameMatches(".*TextView$"));
- assertEquals(addNote.getText(),"Add note");
通过正则表达式判断className是否和预期的一致,注意正则表达式的限制和章节2.4描述的一致。
4. 通过伪xpath方法定位
4.1 通过UiSelector.fromParent或UiObject.getFromParent方法
- save = new UiObject(new UiSelector().text("Save"));
- assertEquals(save.getText(),"Save");
- delete = save.getFromParent(new UiSelector().text("Delete"));
- assertEquals(delete.getText(),"Delete");
UiSelector.fromParent方法(这个例子有点迂回笨拙,但为了演示功能就将就着看吧):
- delete = new UiObject(new UiSelector().text("Save").fromParent(new UiSelector().text("Delete")));
- assertEquals(delete.getText(),"Delete");
4.2 通过UiSelector.childSelector或UiObject.getChild方法
- UiObject parentView = new UiObject(new UiSelector().className("android.view.View"));
- save = parentView.getChild(new UiSelector().text("Save"));
- assertEquals(save.getText(),"Save");
UiSelector.childSelector方法:
- save = new UiObject(new UiSelector().className("android.view.View").childSelector(new UiSelector().text("Save")));
- assertEquals(save.getText(),"Save");
5. 通过控件ID定位
5.1 UiSelector.resourceId方法
- addNote = new UiObject(new UiSelector().resourceId("android:id/title"));
- assertEquals(addNote.getText(),"Add note");
5.2 UiSelector.resourceIdMatches方法
- addNote = new UiObject(new UiSelector().resourceIdMatches(".+id/title"));
- assertEquals(addNote.getText(),"Add note");
注意正则表达式的限制和章节2.4描述的一致
6. 通过contentDescription定位
- 有些控件使用其他办法很难或者根本没有办法定位
- 最重要的是给每个控件的contentDescription设计个唯一值让我们可以非常快速的定位控件,让我们足够敏捷!
6.1 UiSelector.description方法
- addNote = new UiObject(new UiSelector().description("AddNoteMenuDesc));
- assertEquals(addNote.getText(),"Add note");
- </pre><h2>6.2 UiSelector.descriptionContains方法</h2></div><div><pre name="code" class="java"> addNote = new UiObject(new UiSelector().descriptionContains("AddNote"));
- assertEquals(addNote.getText(),"Add note");
6.3 UiSelector.descriptionStartWith方法
- addNote = new UiObject(new UiSelector().descriptionStartsWith("AddNote"));
- assertEquals(addNote.getText(),"Add note");
6.4 UiSelector.descriptionMatches方法
- //addNote = new UiObject(new UiSelector().descriptionMatches("^AddNote.*$"));
- //assertEquals(addNote.getText(),"Add note");
7.通过其他方法定位
除了以上比较常用的方法外,UIAutomator还支持其他一些方法,比如根据控件属性是否可点击可聚焦可长按等来缩小要定位的控件的范围,具体使用方法不一一列举,可以查看以下测试验证代码。
- package majcit.com.UIAutomatorDemo;
- import com.android.uiautomator.core.UiDevice;
- import com.android.uiautomator.core.UiObject;
- import com.android.uiautomator.core.UiObjectNotFoundException;
- import com.android.uiautomator.core.UiScrollable;
- import com.android.uiautomator.core.UiSelector;
- import com.android.uiautomator.testrunner.UiAutomatorTestCase;
- import static org.hamcrest.Matchers.*;
- import static org.hamcrest.MatcherAssert.assertThat;
- public class UISelectorFindElementTest extends UiAutomatorTestCase {
- public void testDemo() throws UiObjectNotFoundException {
- UiDevice device = getUiDevice();
- device.pressHome();
- // Start Notepad
- UiObject appNotes = new UiObject(new UiSelector().text("Notes"));
- appNotes.click();
- //Sleep 3 seconds till the app get ready
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- //Evoke the system menu option
- device.pressMenu();
- UiObject addNote = new UiObject(new UiSelector().text("Add note"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject (new UiSelector().checked(false).clickable(true));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().className("android.widget.TextView").text("Add note"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().classNameMatches(".*TextView$"));
- assertEquals(addNote.getText(),"Add note");
- //addNote = new UiObject(new UiSelector().description("AddNoteMenuDesc));
- //assertEquals(addNote.getText(),"Add note");
- //addNote = new UiObject(new UiSelector().descriptionContains("AddNote"));
- //assertEquals(addNote.getText(),"Add note");
- //addNote = new UiObject(new UiSelector().descriptionStartsWith("AddNote"));
- //assertEquals(addNote.getText(),"Add note");
- //addNote = new UiObject(new UiSelector().descriptionMatches("^AddNote.*$"));
- //assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().focusable(true).text("Add note"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().focused(false).text("Add note"));
- assertEquals(addNote.getText(),"Add note");
- //TBD
- //addNote = new UiObject(new UiSelector().fromParent(selector))
- addNote = new UiObject(new UiSelector().index(0).text("Add note"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().className("android.widget.TextView").enabled(true).instance(0));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().longClickable(false).text("Add note"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().text("Add note"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().textContains("Add"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().textStartsWith("Add"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().textMatches("Add.*"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().resourceId("android:id/title"));
- assertEquals(addNote.getText(),"Add note");
- addNote = new UiObject(new UiSelector().resourceIdMatches(".+id/title"));
- assertEquals(addNote.getText(),"Add note");
- //Go to the editor activity, need to cancel menu options first
- device.pressMenu();
- //Find out the new added note entry
- UiScrollable noteList = new UiScrollable( new UiSelector().className("android.widget.ListView"));
- //UiScrollable noteList = new UiScrollable( new UiSelector().scrollable(true));
- UiObject note = null;
- if(noteList.exists()) {
- note = noteList.getChildByText(new UiSelector().className("android.widget.TextView"), "Note1", true);
- //note = noteList.getChildByText(new UiSelector().text("Note1"), "Note1", true);
- }
- else {
- note = new UiObject(new UiSelector().text("Note1"));
- }
- assertNotNull(note);
- //Go to the NoteEditor activity
- note.click();
- device.pressMenu();
- UiObject save = null;
- UiObject delete = null;
- save = new UiObject(new UiSelector().text("Save"));
- assertEquals(save.getText(),"Save");
- delete = save.getFromParent(new UiSelector().text("Delete"));
- assertEquals(delete.getText(),"Delete");
- delete = new UiObject(new UiSelector().text("Save").fromParent(new UiSelector().text("Delete")));
- assertEquals(delete.getText(),"Delete");
- save = new UiObject(new UiSelector().className("android.view.View").childSelector(new UiSelector().text("Save")));
- assertEquals(save.getText(),"Save");
- UiObject parentView = new UiObject(new UiSelector().className("android.view.View"));
- save = parentView.getChild(new UiSelector().text("Save"));
- assertEquals(save.getText(),"Save");
- }
- }
【转】UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)的更多相关文章
- UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
在本人之前的一篇文章<<Appium基于安卓的各种FindElement的控件定位方法实践和建议>>第二章节谈到Appium可以通过使用UIAutomator的方法去定位And ...
- UIAutomator定位Android控件的方法
UIAutomator各种控件定位的方法. 1. 背景 使用SDK自带的NotePad应用,尝试去获得在NotesList那个Activity里的Menu Options上面的那个Add note菜单 ...
- 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框架是如何定位Android界面上的控件的. UIAutomator定位Android控件的方法实践和建议Appium基于安卓的各种FindEl ...
- 转载:Robotium之Android控件定位实践和建议(Appium/UIAutomator姊妹篇)
来源于:http://blog.csdn.net/zhubaitian/article/details/39803857 1. 背景 为保持这个系列的一致性,我们继续用SDK自带的NotePad实例应 ...
- xe6 android控件透明度设置方法
今天才知道xe6 android控件的透明度设置方法:只需设置控件中的Opacity参数,默认为1--不透明 panel1.Opacity:=0.60;
- Android 控件架构及View、ViewGroup的测量
附录:示例代码地址 控件在Android开发的过程中是必不可少的,无论是我们在使用系统控件还是自定义的控件.下面我们将讲解一下Android的控件架构,以及如何实现自定义控件. 1.Android控件 ...
- 从Android系统出发,分析Android控件构架
从Android系统出发,分析Android控件构架 Android中所有的控件追溯到根源,就是View 和ViewGroup,相信这个大家都知道,但是大家也许会不太清楚它们之间的具体关系是什么,在A ...
随机推荐
- Java他们其中一个IO(一)
1.I/O 操作的目标 其中从数据源读取数据,和写数据到的目标位置数据. 2.IO 的分类方法 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTc ...
- SqlServer中存储过程中将Exec的执行结果赋值给变量输出
原文 SqlServer中存储过程中将Exec的执行结果赋值给变量输出 背景: 遇到这样一种情况:动态向存储过程中传入表名和表的某些属性(这里用到的是主键ID),然后利用这两个变量查出一条数据的某些字 ...
- 原产地政策,jsonp跨域
一.同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最主要的安全功能,假设缺少了同源策略,则浏览器的正常功能可能都会受到影响.能够 ...
- StackExchange.Redis 使用-配置 (四)
Configurationredis有很多不同的方法来配置连接字符串 , StackExchange.Redis 提供了一个丰富的配置模型,当调用Connect 或者 ConnectAsync 时需要 ...
- NET MVC过滤器
NET MVC过滤器 本系列目录:ASP.NET MVC4入门到精通系列目录汇总 在ASP.NET MVC中有四种过滤器类型
- solr/solrj原子更新
lucene原子更新自己不用多介绍,但solr它的包装,下面是一个简单的介绍是:这个操作是用于索引非常有用. 详细在代码中使用例如以下: /** * 原子更新方式 * */ public static ...
- MVC5 Entity Framework学习之实现继承
之前你已经学习了怎样处理并发异常,在本节中你将学习怎样实现继承. 在面向对象的编程中,你能够使用继承来重用代码.接下来你将改动Instructor和Student类,让它们派生自Person基类,该基 ...
- Android文本Flood it游戏源代码
flood_it 流行的Flood it游戏的Android版 游戏玩法: 按下屏幕下方的颜色button,左上角的色块就会变颜色.仅仅要把整片色块变成同色就赢了. 效果图 <ignore_js ...
- 阿里巴巴2014研发project师实习生面试经历
java研发project师的初面是在上周三进行的,终于结果到了晚上才出,而没有通过的则是一结束网上就更新了状态.之后阿里通知这周三,也就是今天进行二面. 凑巧的是今早被舍友吵醒,中午那个困啊,但没时 ...
- yii组态 redis主从配置(随着代码)
最近的欲望redis 主从,但yii内建的redis 它不支持主从.不仅写了一个好办法 结构例,以下: 1.main.php通过添加下面的句子: //redis缓存配置 'cache_redis' = ...