Android UI自动化测试这块一直是google忽略或者技术薄弱的地方,以至于他没有提供一套完整的自动化测试框架。国内公司做UI自动化测试一般都借助于第三方测试框架如robotium,淘宝测试(TMTS),Robolectric等。但这些测试框架或多或少都存在一些跨应用,事件等待等不足,无法满足UI自动化的所有要求。
Android4.0之后,google仿照微软UIAutomation引入了UIAutomator测试框架,虽然是刚刚推出,各个细节还比较粗糙,但毕竟是Android原生的测试技术,再加上这套东西微软已经使用了多年,已经是很成熟了, 所以相对第三方测试框架还是比较有优势的。接触到uiautomator之后我第一个想法就是可以仿照微软POM/LFM将测试代码写得更加优雅。整个思路就是一个分层设计,控件的定义,和控件的操作分为两层,而测试方法调用底下两层,做为第三层。这么设计的好处是明显的:较少代码编写量,并可以在团队写代码中更加容易保持代码风格;代码易维护,改动任何一层代码对其他层影响较小;可以针对Android系统泛滥的弊端针对不同的android系统或手机,生成一种通用库,这样很容易做手机多机适配运行;另外针对POM层,只要代码格式设计完成,可以适当扩展Uiautomatorviewer以自动生成代码(我扩展了右边栏的TreeView,增加了双击自动生成代码保存到剪切板里,这样想要生成哪个控件的定义代码,双击,粘贴一下就行了,非常方便)设计图如下:
最终代码是这个样子的:
public void testSendPicByLocal() {
this.lfm.openApp();
this.lfm.goTabMessagesByXY(); Uia.hand.clickAndWaitForNewWindow( this.pom.messages.relativeLayoutChatSession(1), "点击回话列表中第一个"); if (this.pom.chat.buttonHoldToRecord().exists()) { Uia.hand.click(this.pom.chat.buttonCancelRecord(), "如果录音按钮存在,则点击关闭"); } Uia.hand.click(this.pom.chat.imageButtonPlus(), "点击+"); for (int loop = 0; loop < 500; loop++) { if (!this.pom.chat.textViewPhotoWhenPlusClicked().exists()) { Uia.hand.click(this.pom.chat.imageButtonPlus(), "加号区域已经收回,点击+再次弹出"); }
Uia.hand.click(this.pom.chat.textViewPhotoWhenPlusClicked(), "点击Photo"); this.lib.lfm.photo.getPhotoFromAlbum(); // 调用公共类库拍照方法,可根据不同手机实例化出不同对象 Uia.hand.click(this.pom.chat.imageViewImageSelected(), "点击右下角对号,确认发送"); } }
那么针对uiautomator的代码自动生成或者说录制怎么做呢?
有一个取巧的办法可以通过UiAutomator将页面所有的控件保存到xml中,然后解析xml,生成POM层的代码,虽然只能简单生成POM层代码,但这至少也减少了百分之三十的编码量。
上述扩展uiautomatorviewer的方式比这种更加方便一点。
其实可以考虑使用AccessibilityService,监控用户输入,在onAccessibilityEvent(AccessibilityEvent)方法中解析Event,根据Event类型和其携带的控件属性生成基于UIAutomator的测试代码,然后将测试代码拉出手机,放入事先建好的工程模板中编译即可。
EventSource eventSource = praser.prase(event.toString()); // 设置筛选条件,选择特定事件生成代码。 if (Config.MatchedEvents.contains(eventSource.getEventType())) { generator.generateCode(template.getMethodStepSteam(eventSource)); }
这里不给出具体实现了。
这里提一下Uiautomator源码的一个小bug,这个bug在最新版的4.2.2里已经修复,但你用uiautomator的时候还得注意一下:
uiautomator4.2.2版本一下引入uiautomator.jar时,凡是继承自uicollection的方法UiObjectNotFoundException都没有被抛出,google的工程师自己catch到给打印出来了,所以你的测试代码没办法catch这个异常,
发现这个bug是在scroll一个feedlist时调用scrollforward的方法,结果总是有异常UiObjectNotFoundException,于是想测试代码catch代码段重新scrollforward一下,结果发现这个异常没有抛出,去官网看wiki文档,确实抛出有写这个方法会抛出这个异常,也去翻看了uiautomator源码,确认了,可就是找不到原因,后来灵光一闪,才确认了引入了4.1.2的uiautomator.jar包,这个包里源码给处理了,google的工程师也会犯这么低级的错误。
在这里强烈鄙视那些转载我博客,不表明出处的网站!!!!!