Appium 以 java 为例,总结下 appium 里的一方法的使用心得

eric · 2014年06月23日 · 最后由 陈雪 回复于 2016年12月12日 · 1793 次阅读
本帖已被设为精华帖!

1、关于没有 name,没有 ID 的元素的定位 --- 通用篇
解题思路:
因为没有 name,id;其实剩下的选择已不多,要么 xpath,要么 className。xpath 木有好印象(稳定性不高,加之 1.0x 后需要写全路径,相当崩溃),我决定十分个人色彩的建议使用 className。
具体方法:
用 className 获取所有该类型的元素;
根据元素的位置确定元素的 index;
获取目标元素。
示例:
List lis = driver.findElementsByClassName("android.widget.ImageView");//获取 ImageView 的所有元素
WebEelement targetEle = lis.get(0);//获取列表中第一个元素

进阶:
你可以自己定义一个 className 的常量,然后封装个方法,提供大家使用:
public List getAllImges(){
List lis = driver.findElementsByClassName(AndroidClassName.IMAGEVIEW);
return lis;
}
使用的时候,就只需要调用此方法就可以了

此方法的好处:通吃的方法,基本可解决定位的问题;能解决多语言(自然语言)的困扰;
缺点:因为系统需要去获取 List,就目前来看,运行效率不是很高,那直接是可以用肉眼看的到的速度在跑。。。

2、关于没有 name,没有 ID 的元素的定位 --- 特用篇
因为是特用,所以需要对页面元素做进一步的分析,找出其中的特性。这些特性主要为 className,index,以及 clickable 等属性。
场景 1:同一个页面有 10 个 ImageView 对象,而我们的目标元素的 index 为 4,而同为 ImageView 且 index 为 4 的页面只有 2 个。那我们就可以根据这 2 个条件来组合查询条件,提高效率。
示例:
List lis = driver.findElementsByAndroidUIAutomator("new UiSelector().className("+"android.widget.ImageView"+").index(4)");
基于这个场景可以封装一个方法:
public List getElementsByClassAndIndex(String classname,int index){
List lis =null;
lis = driver.findElementsByAndroidUIAutomator("new UiSelector().className("+classname+").index("+index+")");
return lis;
}

场景 2:同一个页面有 10 个 ImageView 对象,而其中 index 为 4 的有 5 个,而这时我们发现我们的目标元素的是 clickable 的。然后 review 页面发现,同时满足上述条件的只有 2 个。那么。。。
示例:
List lis = driver.findElementsByAndroidUIAutomator("new UiSelector().className("+"android.widget.ImageView"+").index(4).clickable(true)");
同样可以封装一个方法:
public List getElementsByClassAndIndexAndClickable(String classname,int index){
List lis =null;
lis = driver.findElementsByAndroidUIAutomator("new UiSelector().className("+classname+").index("+index+").clickable(true)");
return lis;
}

场景 3:在分析页面元素的时候发现,页面相对比较简单,而且其中只有目标元素的 index 为 4.
示例:
driver.findElementByAndroidUIAutomator("new UiSelector().index("+index+")");
同样得到一个方法
public WebElement getElementByIndex(int index){
return driver.findElementByAndroidUIAutomator("new UiSelector().index("+index+")");
}

3、关于输入框有默认 text,且当你选中时,不会清空的清空的处理。
类似的情况,用 element.clear() 是没有效果的。那怎么办呢? 不急,appium 提供了很多的操作,直击不行,我们就上组合拳。
示例:
public void clear(WebElement el){
el.click(); //选中输入框
driver.sendKeyEvent(123);//将光标移到最后
String txt = el.getText(); //获取字符串长度
for(int i=0;i<txt.length();i++){
driver.sendKeyEvent(67);//一个个的删除。。。。。
}
}

4、关于 UiAutomator 无法识别的元素
整体思路:不要忘了咱的手机是可以点击的。
获取相对坐标,点击,就这么简单。(不用绝对坐标是保证程序能在不同的分辨率下运行)
下面一起讨论下相对坐标的获取:找一个页面,这个页面上有相关的元素的位置与目标位置类似,或者根据这些元素能获取到目标的大致位置。
上段代码,帮助理解:
public List getFileMngPoint(){
List list = new ArrayList();
WebElement scrol = driver.findElementByClassName(AndroidClassName.HORIZONTALSCROLL);
List imgs = scrol.findElements(By.className(AndroidClassName.IMAGEVIEW));
//以上仅获取类似位置的元素
Point e0 = getCenterPoint(imgs.get(0));
Point e1 = getCenterPoint(imgs.get(1), imgs.get(2));
Point e2 = getCenterPoint(imgs.get(3));
Point e4 = getCenterPoint(imgs.get(2),imgs.get(3));
Point e5 = getCenterPoint(getElementsByClassAndIndexAndClickable(AndroidClassName.IMAGEVIEW, 0).get(4));
//以上获取元素的中心坐标,相关方法是自己写的
list.add(e0);
list.add(e1);
list.add(e2);
list.add(e4);
list.add(e5);

return list;
}

思考:
关于使用 className 的方法时,如果我们的 list 能在页面加载完成之后就能被缓存起来,那么其运行效率还能提高不少

欢迎添加其他心得~~~~

共收到 21 条回复 时间 点赞

顶一下

xpath 也挺好 pc 端的 webdriver 经常用

希望这样的帖子越来越多,赞

支持一下啦!学习了!

写的很好,提供了新的思路。
不过实际工作中如果遇到问题,最好与开发项目组协调,要求添加 id 和 name 等基本属性。

赞 我是亲眼见证了这么多人才的成长啊

#6 楼 @oneway 我也觉得这样的最快速的办法

真是及时雨啊!appium for windows 无法获取 xpath,我都不知道怎么定位了。炒鸡赞!!!

赞,学习了, 谢谢分享。

想知道中文输入怎么解决。。。

@eric 第四种方法可以说具体点吗?有点点看不懂

eric #14 · 2014年12月25日 Author

@woshizh 思路就是通过坐标去点击,先找到能找到的元素,获取屏幕的相对坐标,让后根据坐标去点目的对象。

@eric 主要是获取中心元素中的 get(0,1,2,3)那段有点难理解。。。思路还是非常明确的~~

eric #16 · 2015年01月07日 Author

@woshizh 这个是在获取相关元素,List imgs = scrol.findElements(By.className(AndroidClassName.IMAGEVIEW)); 返回的是一个列表,imgs.get(0) 就是获取这个列表的第一个元素。

@eric 哦哦,都懂了,我试下,非常感谢解答。

非常不错,谢谢分享

driver.findElementsByAndroidUIAutomator 这个方法在 1.4 中没有看到 ,变成什么样了。

解决了我的问题,非常感谢~~

WebElement scrol = driver.findElementByClassName(AndroidClassName.HORIZONTALSCROLL);中 AndroidClassName 具体是指什么?是那个位置元素的 class 值么?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册