小程序自动化测试框架原理剖析
01
智能小程序架构设计
既然是对智能小程序自动化测试框架的剖析,免不了先得聊聊智能小程序的架构设计。
如图所示便是智能小程序的一个简要的架构设计图:
运行设备指的是我们平时使用的 android 或者 iOS 手机,宿主 APP 指的是 百度 APP 以及其它智能小程序开源联盟合作伙伴 APP,如爱奇艺、wifi 万能钥匙等。
当然智能小程序有一个独特的特性,可以为开发者自动生成一个 H5 形态的小程序,支持直接运行在浏览器上的,这时候运行设备指的就是咱们的个人电脑/手机,而宿主 APP 指的就是浏览器了。
当我们用手机打开百度 APP 上的某个小程序的时候,百度 APP 会为这个小程序单独开启一个进程,并在这个进程里开启一个 Logic 线程和多个 View 线程。
小程序的所有业务逻辑都集中在 Logic 线程,而 View 线程就是我们所看到的小程序的各个页面,Logic 线程和 View 线程通过宿主 APP 集成的小程序框架 SDK(swan sdk)提供的 eventBus 进行双向通信。
举个例子,我们看到的小程序的首页(页面 A),其实是一个 View 线程(view1),当我们点击上面的一个按钮的时候,点击事件会经 eventBus 由 swan sdk 传回到 Logic 线程,Logic 线程根据开发者绑定的处理函数调用 swan.navigateTo 方法触发跳转页面 B,页面调整指令由 Logic 线程传递到 swan sdk,swan sdk 创建一个新的 View 线程( view2)渲染页面 B 并将 view 推至前台展示在用户面前,最后通过 eventBus 告知 Logic 线程页面创建完毕,完成一次点击事件的处理。
这里的 Logic 线程,随着宿主 APP 的实现不同,承载实现的容器可能是 webview,也可能是 v8 或 Jsc。而 View 线程则有可能是 webview,或者native的嵌套方案。
上述,其实只是提及了智能小程序框架架构设计一个大概,为了方便大家理解,抹平了很多细节上的东西。
在基本了解了智能小程序的架构设计后,让我们一起来看看 smartapp-automator 自动化测试框架的架构设计。
02
自动化测试框架架构设计
如图所示便是 smartapp-automator 的一个全局架构图:
化繁为简来说的话,其实整个设计就包含了两个部分:对智能小程序运行时的自动化操控部分,和对各类设备的自动化操控部分,咱们分别展开来看看。
03
智能小程序的自动化操控
从刚刚智能小程序架构设计的剖析中,我们可以发现,智能小程序的架构设计不同于 H5/Native,是多种技术的混合产物,因此很难用 Appium、Selenium 等现成工具组合后对智能小程序进行操控。
因此,我们参考 selenium 1.0 及 chrome debug protocol,设计实现了智能小程序测试引擎,通过智能小程序测试引擎,将智能小程序的自动化操控能力给外透了出来。
智能小程序测试引擎的整体架构设计长这样:
从图中可以看到,智能小程序测试引擎包含 4 个部分:
位于智能小程序运行时 Logic 线程内的 batEngineLogic 模块 位于智能小程序运行时 View 线程内的 batEngineView 模块 同 batEngineLogic 经由 websocket 进行双向通信的 bat-agent 模块 同 bat-agent 经由 websocket 进行双向通信的 bat-driver 模块
在小程序调试模式开启后,我们去打开一个智能小程序,Logic 和 View 线程都会在框架初始化的时候分别动态扩展 batEngineLogic 和 batEngineView。
batEngineLogic 模块是一个 websocket client,在加载后会主动寻找 bat-agent(websocket server)并进行连接。
bat-agent 会在 smartapp-automator 实例化后启动,它接收来自运行设备上 batEngineLogic 的连接,同时接收 bat-driver 的连接,负责将 bat-driver 的指令请求转发到 batEngineLogic 同时接收 batEngineLogic 消息反馈给 bat-driver。
bat-driver 定义了一套 API,供 smartapp-automator 调用,指令经 bat-agent 传达到 batEngineLogic 执行,然后再经 bat-agent 获得结果反馈,从而达到操控小程序的目的。
batEngineLogic 模块和 batEngineView 模块之间通过 eventBus 双向通信,如果我们想要获取页面实际的渲染情况/直接对页面进行控制,则需经 batEngineLogic 模块将指令转发到 batEngineView 模块。
根据上述描述,大家可以发现,整个架构设计充斥了双向通信。双向通信给我们的程序实现带来了复杂性,但也给我们测试框架的应用前景带来了更多的可能性。
举个简单的例子,有了这三层双向通信,我们便可以在 smartapp-automator 层对真机设备层小程序页面的点击或其它事件进行监听及信息捕获,基于这个特性,我们最终设计实现了基于真机操作的 UI 用例录制回放工具,解放了 UI 类自动化用例编写的成本。
04
设备的自动化操控
设备有很多种类型,比如 Android 手机、iOS 手机、PC 机、Android 开发板、百度云 Android 云手机、IOT 设备等。
针对这些设备,业界或多或少都沉淀了一系列可用的工具,比如,Android 手机/开发板可以用 adb 工具、Uiautomator2 操控,iOS 手机可以用 wda 操控,PC 机上的 Chrome/Chromium 浏览器可以用 puppeteer,百度云云手机提供了 bacagent 工具。
如果让 smartapp-automator 的用户,根据设备类型的不同去自行选用对应的设备操控工具,那用户的使用成本将会非常巨大。
因此,如图所示,我们在 smartapp-automator 提供了一套统一的设备操控 API,在这层 API 之下,我们使用不同的操控工具对各类型设备操控能力进行了封装。这样,用户无需考虑设备类型/对应的操控工具,直接使用 smartapp-automator 提供的统一操控 API 便可完成对设备的操控。
在设备操控能力具体的实现上,这里陈列下我们针对不同设备类型的一个选型:
Android: Adb: https://developer.android.google.cn/studio/command-line/adb Atx-Agent: https://github.com/openatx/atx-agent iOS: Wda: https://github.com/openatx/facebook-wda Chrome/Chromium Puppeteer: https://github.com/puppeteer/puppeteer
因为 smartapp-automator 是基于 NodeJS 编写的,而上述工具所使用的语言各不相同,所以普遍采取了自行封装驱动层的做法来接入使用。
05
总结