UiAutomator 自动遍历 APP,如何判断 UI 界面是否改变?

何畅 · 2016年11月28日 · 最后由 在路上 回复于 2019年06月21日 · 5541 次阅读

想用 uiautomator 做 Android 自动遍历测试,但如何判断 UI 界面是否改变呢?
结合论坛中几位大神的思路,综合起来有以下几种思路,但又都有疑问:

1.采用 MD5 编码:
但这个码具有高度的离散性,也就是说,原信息的一点点变化就会导致 MD5 的巨大变化,而如果 UI 界面上有微小的改动却不能认为其改变,那么采用 MD5 编码意义何在??

2.采用界面上控件的 TEXT 文案作为标志:
那么有的界面是有滚动图的,那么文字是滚动的,这又如何处理?有人的解决方案是,设置一些黑名单,把这类文字去掉,那么每天文案都会刷新,难道遍历工具每天也要跟随着改变吗?有点麻烦了是不是。。。

3.采用界面上控件的类名以及 ID 区分:
但是有些页面上控件是一样的,只是控件里的文字不一样,这时该怎么算??而且如果有滚动显示的内容,即使采用黑名单的方法也去不掉了。。。。

一直被以上几点疑问困扰着,也找不到完美的解决方法,请各位指点!

共收到 22 条回复 时间 点赞

有没有尝试过用 xpath 去判断呢?

把界面 xml 拿出来,遍历它,得到所有控件及 id,以图片对比为辅,这是我的想法

—— 来自 TesterHome 官方 安卓客户端

动态页面的坑,这个比较难

#1 楼 @haos 我知道用 xpath 可以去过滤控件,但现在我可以用 uiautomator 中的函数来过滤,你说用 xpath 具体是什么思想呢??

#2 楼 @heyniu 用控件的 id 来做严格对比吗?那万一有个微小的变化怎么处理呢?

#3 楼 @kasi 是呢,您是怎么填平这个坑的呢??

#4 楼 @chorushe 不关心 UI 更新,记录操作过的控件 xpath(xpath 格式自己定义,可以是控件的路径,甚至是 xpath+text),即使 ui 变化出现新的控件或者已存在的控件的 text 发生变化那么其 xpath 一般可以看作未操作过的;

如果没有动态变化可以用句柄,用 sufaceflinger 获取的,动态变化只能用 xpath 了

#7 楼 @haos 如果不关心 UI 更新,那就只能一路点下去,怎么进行页面回退判断呢?

#9 楼 @chorushe 维护操作过的 xpath(xpath 可以用 list 维护,activity 作为 key,以上存到 map),当前页面 xpath 全部遍历完就回退。

木有玩过,。。

何畅 #12 · 2016年11月30日 Author

#10 楼 @haos 太棒了,解决了我很久的困惑,感谢!我整合一下思路,如有疑问还希望能与您继续讨论~~

何畅 #13 · 2016年11月30日 Author

#11 楼 @bailin 一起玩呀~~~

我去年有写过,我是用 xml 来判断的,我的做法是:
来到一个新页面,保存 xml + title + activity 名字
与之前同类型的 xml 比较,我设定了一个阈值,小于阈值救人为是相同的页面

何畅 #15 · 2016年11月30日 Author

#14 楼 @ruru 我也想过通过 xml 文件作比较,可是 xml 比较是怎么做到的呢??

#9 楼 @chorushe 关于页面窗口的变化,可以分两种,一种是页面窗口发生了跳转,比如点开进入了另一个 activity,或是弹出了 popupwinow 对话框,这些都导致窗口焦点发生改变;还有一种属于页面内容的变化,比如点击了一个 tab 选项卡,导致 fragment 切换,但此时页面 window 还是之前 activity,只是 activity 页面上的内容或结构变化。对于这两种变化,在遍历的时候要能区分识别和对待才能使遍历顺利进行。
关于第一种焦点变化的识别:
可以通过 getRuntime 方法获取运行时,取得输入输出流向安卓输入 shell 命令,dumpsys window windows 可获取屏幕当前获取焦点窗口,(可以在 pc 机上先通过 cmd 进入命令行,输入 adb shell,再输入 dumpsys window windows | grep mCurrent 试一下,看一下输出结果。)输出的结果有当前聚焦窗口的对象地址名,所属应用名,以及 activity 名 (如果是弹出窗,就直接显示 popupwindow),通过该方法可标识当前窗口是否跳转到了新页面 (如果 activity 名称发生变化,则一定跳转,如果 activity 名称不变,地址发生变化,则肯定也是发生了跳转)。
关于第二种变化,即:
点击控件后,当前聚焦窗口地址和 activity 名都没变化,但页面内容发生了变化。此时就需要通过对比生成的 xml 控件数据文件来判定。一般可先将页面上的 text 先取出,对比前后顺序和内容有无改变,还有控件坐标位置取出,看控件是否移位,还有对比是否可用属性等等,这些操作可能耗时,有损遍历效率,需根据实际业务情况斟酌使用。总之,如果页面内容发生了变化,一定要重新更新窗口状态信息,以页面变化后的控件信息和位置为准。

—— 来自 TesterHome 官方 安卓客户端

关于页面窗口的变化,可以分两种,一种是页面窗口发生了跳转,比如点开进入了另一个 activity,或是弹出了 popupwinow 对话框,这些都导致窗口焦点发生改变;还有一种属于页面内容的变化,比如点击了一个 tab 选项卡,导致 fragment 切换,但此时页面 window 还是之前 activity,只是 activity 页面上的内容或结构变化。对于这两种变化,在遍历的时候要能区分识别和对待才能使遍历顺利进行。
关于第一种焦点变化的识别:
可以通过 getRuntime 方法获取运行时,取得输入输出流向安卓输入 shell 命令,dumpsys window windows 可获取屏幕当前获取焦点窗口,(可以在 pc 机上先通过 cmd 进入命令行,输入 adb shell,再输入 dumpsys window windows | grep mCurrent 试一下,看一下输出结果。)输出的结果有当前聚焦窗口的对象地址名,所属应用名,以及 activity 名 (如果是弹出窗,就直接显示 popupwindow),通过该方法可标识当前窗口是否跳转到了新页面 (如果 activity 名称发生变化,则一定跳转,如果 activity 名称不变,地址发生变化,则肯定也是发生了跳转)。
关于第二种变化,即:
点击控件后,当前聚焦窗口地址和 activity 名都没变化,但页面内容发生了变化。此时就需要通过对比生成的 xml 控件数据文件来判定。一般可先将页面上的 text 先取出,对比前后顺序和内容有无改变,还有控件坐标位置取出,看控件是否移位,还有对比是否可用属性等等,这些操作可能耗时,有损遍历效率,需根据实际业务情况斟酌使用。总之,如果页面内容发生了变化,一定要重新更新窗口状态信息,以页面变化后的控件信息和位置为准。

—— 来自 TesterHome 官方 安卓客户端

#17 楼 @williamliuok 一开始以为没评论成功,一不小心发了两条。

—— 来自 TesterHome 官方 安卓客户端

何畅 #19 · 2016年12月15日 Author

#18 楼 @williamliuok 非常感谢您的详细回复,很受教,那么想继续追问个问题:关于无法用 back 键恢复的界面,您是怎么遍历其他按钮的呢?或者是也可以理解成,back 键直至退出 APP 了以后如何继续遍历那些为遍历的控件呢?我目前遍历后的遍历比率特别低,一些页面几乎是点击一个按钮就没再恢复了。
感谢!

#19 楼 @chorushe 加个微信聊,这里不方便。william6902

—— 来自 TesterHome 官方 安卓客户端

何畅 #21 · 2016年12月23日 Author

#20 楼 @williamliuok 已加微信 🙏 🙏

何畅 回复

想问一下楼主,这个问题有效解决了吗?

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