MonkeyRunner框架暴露了几个类的大量的API出去给用户编写脚本时候使用,其中最主要的三个就是: MonkeyDevice目标设备操作类,HierarchyViewer窗口界面对象操作类以及MonkeyImage这个截屏处理类。了解了这3个类以及跟他们相关的关键类的实现原理,基本上可以说MonkeyRunner框架的实现原理就算搞清楚了。因为一个UI自动化测试框架的关键功能无非就是这三样: 操作目标设备,如注射点击事件等;获取控件信息,如获取需要点击的控件的中心坐标等;结果比较。其实这3个类也就是我们往下章节分析的重点。
操作目标设备和获取控件信息的重要性我们很容易理解,但是截屏处理为什么也这么重要呢?这是因为MonkeyRunner没有集成如Junit等单元测试框架,它也并不完全是一个如UiAutomator,Robotium或者Appium等的面向控件的自动化测试框架,所以它的执行结果比较的功能主要就是通过比较截屏和预期结果是否是一致的来判断我们的测试用例是否应该通过的。
所以本章我们先去分析的就是MonkeyImage这个类。在MonkeyRunner框架中,主要用到的库除了自身monkeyrunner这个库之外,还会经常用到chimpchat和ddmlib这两个库,这个我们在上一章已经见识过了。下面我们就先看下MonkeyImage相关类的类图,然后做简要的描述,之后会在本章独立的章节对关键的类进行相应的分析和阐述。
图9-1-1 MonkeyImage关键类关系图
- MonkeyRunner: MonkeyRunner这个类在这里的主要作用是它提供了loadImageFromFile给用户在编写脚本时调用。该方法的目的是调用依赖的ChimpImageBase抽象类的静态方法loadImageFromFile去指定的路径把一个文件读取出来并事例化成BufferedImage对象,比如把之前保存好的作为预期结果的截屏文件读出来,然后再去跟通过调用MonkeyDevice的getSnapshot方法获得的截屏进行比较以确定该界面是否有变化
- MonkeyImage: 类似于MonkeyDevice提供了用户操作目标安卓设备的接口,MonkeyImage类提供了用户处理图片的接口方法。要注意的是真正去截屏的操作还是需要调用MonkeyDevice的takeSnapshot方法去完成的,因为MonkeyImage并不会提供与设备交互的功能,它只提供图片处理的功能。这里要注意的是MonkeyImage的成员变量IChimpImage类型的impl,IChimpImage是个接口,AdbChimpImage类是该接口的实现类,在用户调用MonkeyDevice的takeSnapshot方法来获取一个截屏的过程中,MonkeyDevice会根据获得的截屏裸图RawImage来构建一个AdbChimpImage的实例,然后将该实例赋予给MonkeyImage的impl成员变量来构建一个MonkeyImage的实例。MonkeyDevice获取截屏的原理分析会在第9章进行详细分析,这里大家只需要指导impl指的就是AdbChimpImage的一个实例就行了
- AdbChimpImage: MonkeyImage对图片的处理会通过请求其聚合的AdbChimpImage的实例来完成。比如用户在脚本调用MonkeyImage的sameAs方法来比较两个截屏是否是一样的时候,MonkeyImage就会调用AdbChimpImage对应的sameAs来进行比较处理,而AdbChimpImage其实并没有去实现sameAs这个方法,该方法真正的实现是在AdbChimpImage的父类ChimpImageBase中实现的。AdbChimpImage持有了一个RawImage裸图的对象,该对象是在用户调用MonkeyDevice的takeSnapshot的过程中构建的。至于RawImage裸图的详细分析,本章和面会又相应的小节专门进行分析
- RawImage: 代表一个裸图的类,是根据”framebuffer:”这个 ADB截屏服务返回来的截屏数据创建的, 该类由ddmlib库提供。下一小节会对framebuffer这个ADB截屏服务进行详细的分析
- ChimpImageBase: AdbChimpImage的父类主要的图片处理方法都在这个类中实现,比如上面提到的sameAs这个图片比较方法,以及其他如getSubImage获取子图的方法等。但需要注意的是该类对图片的处理使用的图片类是BufferedImage这个由Java的AWT库提供的通用类,而非ddmlib提供的RawImage这个安卓专用的裸图类。ChimpImageBase同时也是IChimpImage接口的实现类,该接口定义了一些子类必须实现的图片处理的方法,比如刚才提到的sameAs和getSubImage
- BufferedImageChimpImage: ChimpImageBase的子类除了有AdbChimpImage这个专门用来处理MonkeyDevice的takeSnapshot返回来的截屏裸图RawImage的类之外,还有一个叫做BufferedImageChimpImage的子类,它是作为ChimpImageBase的内部类来实现的。它跟AdbChimpImage类在整个类关系图中处于同一个水平,相对AdbChimpImage是用来处理takeSnapshot返回的截屏,BufferedImageChimpImage类更多是用来处理从文件中加载的图片和getSubImage获取到的子图图片。它拥有的通用类BufferedImage的实例image会让这些处理更加简单快捷
- IChimpImage: ChimpChat库的图片处理接口,定义了子类需要实现的最基本的图片处理方法