SIFT+KNN加持下的Android测试自动化脚本
Keep Team Lv4

  在之前的尝试(折腾)中 (参见《基于图像识别与位置关系的Android控件遍历方式》),我尝试基于简单的图像比对技术,做了一个没啥用的Android App测试自动化脚本。但是该脚本存在识别率低,耗时长等诸多问题。而用Airtest自带的图像比对功能又极易找错控件(可能是我使用姿势不对)。因此我在Github上搜寻了很久能快速完成图像比对的算法。虽然找了很多但是效果却不是特别好,要么超级复杂(完全不知道在干什么),要么耗时非常长(最长的能到10分钟),所幸在Github上搜索的时候了解到不少之前都不曾听过的算法,比如SIFT、SURF等等。行吧,还是自己正面刚吧。

算法

  经过简单的网上自学,大体上选择了SIFTORB以及SURF作为关键点检测算法,并选择FlannBrute Force作为匹配算法。这些算法具体的工作原理,我也不懂,但是他们组合在一起的工作流程,大致如下:

流程图

  正如上文所述,关键点检测算法和匹配算法并不是唯一的,相互之间也并无固定搭配关系,因此我们根据实际情况选择最适合的算法即可。在脚本confidence.py中已利用Python实现了相关算法的调用。

def _sift_detect(*imgs):
    ...
def _orb_detect(*imgs):
    ...
def _surf_detect(*imgs):
    ...
def _bf_knn_match(des1, des2, ratio=0.75):
    ...
def _flann_knn_match(des1, des2, ratio=0.4):
    ...

  具体实现,请点击查看。需要注意的是,参数中的ratio默认值均为经验值,并非固定值。有了算法的调用,那么剩下的就只需要将算法进行组合即可。组合可参考博文《应用OpenCV和Python进行SIFT算法的实现》(该博文对我启发挺多,特此感谢)。
  实际测试下来,发现不同组合方式,算法的耗时差别不大(大约在0.4s至0.7s之间,如果取消掉调试显示,速度还会更快),而实际匹配效果SIFT + KNN要好很多。

匹配逻辑

  在之前我们尝试的遍历逻辑很简单,只要发现有可操作(可点击)控件,则触发点击,然后循环往复。一句话描述那就是“一点到底”。虽然很简单粗暴,但是遇到以下情况则会整个人都变得不好了。

无限套娃

  我们假设存在这样一个APP,每个界面对外提供的按钮、输入框等人机交互接口均是下一个功能的入口(即发生界面的跳转)。那么我们只要按照二叉树遍历的方式一层一层往下走终会完成所有入口的遍历(这也是为什么之前采用简单粗暴的循环遍历)。

二叉树

  现在我们进一步假设,如果这些功能入口之间存在联通的情况,那么就由变为了,而且这个图在未完全遍历的情况下,可能存在无限的路径以及虚拟路径(如上图套娃示例,UI上已有明显的变化,但是Activity并无跳转)

图

  所以需要引入限制机制,防止套娃引起的脚本“死循环”。这里引入了测试深度。我们假设发生了“套娃”,对于程序来讲,它会认为实际执行路径如下:

depth

  虽然UI上能明显感知到是在A与B之间不停的来回跳转,但是程序却很开心的认为自己发现了好多好多新的界面。如果我们给A与B增加了Depth属性,情况就会变得不太一样。
  假设每个控件初始Depth为2,每访问一次则减1,当循环到图中A的Depth为0时,程序就可以以此为依据跳出当前循环,打破“套娃”魔咒。

比对实现效果

bt_1

bt_2

account_1

account_2

遗留问题

  部分控件匹配不上。目前原因未知,猜测是特征点太少导致无法匹配。后续做针对性的进行分析和优化吧。

  • 当前发现无法匹配上的图形有:

disable_button

代码已归档至Gitee