Android自动化测试处理各种弹窗的操作方法
在UI自动化测试中弹窗是影响自动化用例稳定性的一大因素如何方便快捷的处理各种情况下的弹窗是搞UI自动化测试必须要面临的问题.弹窗的种类:安装APP时的系统弹窗 此类弹窗一般有两种一种是自动化测试框初始化本身也需要安装一些APP比如uiautomator2会安装atx-agent、com.github.uiautomator这些弹窗在初始化环境的时候可以手动点掉case里不需要关注。另一种就是安装我们的被测app像下面这种都是我们不得不去处理的不然自动化也就是不自动了。 APP启动时的权限弹窗这类弹窗是APP在启动时会申请一些基础的权限APP内的业务弹窗弹窗处理本文使用的是uiautomator2这个自动化框架它提供了一种watcher对象可以用来配置要监控的元素这里我们配置要监控的就是页面上的弹窗下面来看看具体怎么做。watcher的使用1234567891011121314151617181920212223242526272829# 常用写法注册匿名监控d.watcher.when(安装).click()# 注册名为ANR的监控当出现ANR和Force Close时点击Force Closed.watcher(ANR).when(xpathANR).when(Force Close).click()# 其他回调例子d.watcher.when(抢红包).press(back)d.watcher.when(//*[text Out of memory]).call(lambda d: d.shell(am force-stop com.im.qq))# 回调说明def click_callback(d: u2.Device):d.xpath(确定).click() # 在回调中调用不会再次触发watcherd.xpath(继续).click() # 使用d.xpath检查元素的时候会触发watcher目前最多触发5次# 移除ANR的监控d.watcher.remove(ANR)# 移除所有的监控d.watcher.remove()# 开始后台监控d.watcher.start()d.watcher.start(2.0) # 默认监控间隔2.0s# 强制运行所有监控d.watcher.run()# 停止监控d.watcher.stop()# 停止并移除所有的监控常用于初始化d.watcher.reset()上面是watcher的一些常用api以及解释来源于github。嘻嘻自己懒的写了。实战案例下面我们用B站apk为例处理从安装到登录后的一系列弹窗。123456789101112131415161718192021222324252627282930313233343536importuiautomator2 as u2importosimporttimebase_dir os.path.dirname(__file__)apk_path os.path.join(base_dir,apks/bilibili.apk)d u2.connect_usb(serialMDX0220924018819)# 从安装到登录成功后可能会出现的弹窗在这里进行注册这个是华为手机出现的弹窗类型d.watcher.when(继续安装).click()d.watcher.when(完成).click()d.watcher.when(同意并继续).click()d.watcher.when(我知道了).click()d.watcher.start()d.app_install(apk_path)d.app_start(tv.danmaku.bili)d(text我的).click()time.sleep(3)ifd(resourceIdtv.danmaku.bili:id/btn_change_account).exists:d(resourceIdtv.danmaku.bili:id/btn_change_account).click()else:d(resourceIdtv.danmaku.bili:id/tv_login).click()time.sleep(3)d(resourceIdtv.danmaku.bili:id/username).set_text(xxxxxxxxx)d(resourceIdtv.danmaku.bili:id/userpwd).set_text(xxxxxxxx)d(resourceIdtv.danmaku.bili:id/log_reg_checkbox).click()time.sleep(2)d(resourceIdtv.danmaku.bili:id/btn_login).click()d(text首页).click()弹窗处理的核心思想是起一个线程不停的监听页面上有没有弹窗出现出现了就点击或点击取消或点击确认等等。uiautomator2处理弹窗的核心思想采用了后台运行了一个线程的方法(依赖threading库然后每隔一段时间dump一次hierarchy 匹配到元素之后执行相应的操作。123456789101112131415classWatcher():def __init__(self, d:uiautomator2.Device):self._d dself._watchers []self._watch_stop_event threading.Event()self._watch_stopped threading.Event()self._watching False # func start is callingself._triggering Falseself.logger setup_logger()self.logger.setLevel(logging.INFO)def when(self, xpathNone):returnXPathWatcher(self, xpath)Watcher对象个self._watchers 属性来维护所有要监控的元素d.watcher.when(继续安装)当我们调用when方法后会返回一个XPathWatcher对象然后再调用这个对象的click方法实现对监控元素的操作。1234567891011121314151617181920212223242526classXPathWatcher():def __init__(self, parent: Watcher, xpath: str, name: str ):self._name nameself._parent parentself._xpath_list [xpath]ifxpathelse[]def when(self, xpathNone):self._xpath_list.append(xpath)returnselfdef call(self, func):func accept argument, key(d, el)dself._d, elelementself._parent._watchers.append({name: self._name,xpaths: self._xpath_list,callback: func,})def click(self):def _inner_click(selector):selector.get_last_match().click()self.call(_inner_click)click方法就是将点击的操作放到回调函数然后调用XPathWatcher对象的call方法这个方法会生成一个监控规则并将监控规则放到我们前面提到的Watcher对象的self._watchers 属性。123456789101112def start(self, interval:float2.0): stop watcher ifself._watching:self.logger.warning(already started)returnself._watching Trueth threading.Thread(namewatcher,targetself._watch_forever,args(interval, ))th.daemon Trueth.start()returnth再然后调用Watcher对象的的start方法开启一个线程按照指定间隔时间从页面dump信息查看是否有要监控的元素找到后调用回调函数。以上是我们关于弹窗处理的一些操作但是有没有发现上面实战哪里写的是有问题难道每一次有新的弹窗都要在这里写一行代码么还有是不是能适配不同机型呢最后下方这份完整的软件测试视频教程已经整理上传完成需要的朋友们可以自行领取【保证100%免费】软件测试面试文档我们学习必然是为了找到高薪的工作下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料并且有字节大佬给出了权威的解答刷完这一套面试资料相信大家都能找到满意的工作。