Macaca Macaca App Inspector 原理解析

达峰的夏天 · 2017年06月03日 · 最后由 达峰的夏天 回复于 2018年03月20日 · 4611 次阅读
本帖已被设为精华帖!

上一篇 - 使用 Macaca 录制器录制脚本

Macaca 提供元素查看器 (app-inspector),能够查看 iOS 和 Android 应用的元素属性值,如 name, id, XPath 等。

app-inspector 有如上几个组成部分,分别介绍主要用途:

  • UIAutomatorWD: UIAutomatorWD 是对 UI Automator 的封装,app-inspector 需要使用 UI Automator 提供的接口获取 Android 系统的 window Hierarchy。这也是 macaca-android 的下层功能模块,可见 app-inspector 使用的驱动层与 macaca-android 是一致的。
  • macaca-adb: ADB 在 app-inspector 启动过程中会操作设备和用来回传截图。
  • XCTestWD: XCTestWD 是对 XCTest 的封装,app-inspector 需要使用 XCTest 提供的接口获取 iOS 系统的 lastSnapshot。这也是 macaca-ios 的下层功能模块,可见 app-inspector 使用的驱动层与 macaca-ios 是一致的。
  • ios-simulator: ios-simulator 用来操作 iOS 模拟器。
  • ios-utils: 此模块提供 iOS SDK 环境检查,获取真机日志输入等功能。

设计原则

  • 跨多端:app-inspector 同时支持两个平台,避免了维护两套环境的困窘。
  • 完全 WEB 化:app-inspector 的实体是一个 WEB 服务,方便各处部署,只要有标准浏览器即可使用。

开放和标准化是贯穿 Macaca 整体的理念,可以看到能够 web 化的工具都是使用 web 实现的。

实现原理

  1. 初始化时启动手机设备上的 UIAutomatorWD 或 XCTestWD 服务
  2. 向 UIAutomatorWD 或 XCTestWD 先后发送 /source/screenshot 请求
  3. 将每次时序获取的截图和 Hierarchy 做映射,渲染到用户浏览器

处理渲染

app-inspector 用户端分三部分,中间的部分用来将界面 Hierarchy 渲染为树形组件。当操作中间的树控件时,将节点的信息同时展示在右侧,同时将节点携带的 width 和 height 坐标等渲染在左侧,高亮显示。

处理事件

export function boundsSize(bounds) {
  const [
    x,
    y,
    width,
    height
  ] = bounds;
  return width * height;
};

export function compareBoundsSize(rectA, rectB) {
  return boundsSize(rectA) > boundsSize(rectB);
};

export function isInRect(x, y, bounds) {
  const [
    _x,
    _y,
    width,
    height
  ] = bounds;

  return x >= _x
    && x <= _x + width
    && y >= _y
    && y <= _y + height;
};

当操作左侧屏幕展示区时,通过后序遍历的方式查找到用户端操作到的区域,然后将后面的遍历操作都终结掉,同时高亮当前区域。

export function getNodePathByXY(tree, isIOS, x, y) {
  let bestBounds = null;
  let bestPath = null;

  function walk(node, path) {
    let bounds = node.bounds;
    let inRect = isInRect(x, y, bounds);

    if (inRect) {
      if (!bestBounds || compareBoundsSize(bestBounds, bounds)) {
        bestBounds = bounds;
        bestPath = path;
      }

      if (node.nodes) {
        node.nodes.forEach((child, index) => {
          walk(child, path.concat([index]));
        });
      }
    }
  }

  walk(tree, []);

  return bestPath;
};

处理 XPath

  1. 当前节点若有唯一 ID,则返回/*[@resource-id="${ID}"]
  2. 当前节点的父节点有没有 ID,若有则采用相对定位
  3. 当前节点若有唯一文本值,则返回/*[@text="${ID}"],其他属性类似
  4. 当前节点若没有命中任何规则,直接返回最长路径

如何应对 Webview

Macaca app-inspector 弥补了社区 Native 元素查看器的空白,Webview 又如何处理?

不建议将 Webview 透出到 Native 元素上来当做 Native 元素处理,虽然 Android 能够这样实现,因为毕竟是已经标准化运行时的 View,暂时没法与 Naitve 等同看待。

由于历史渊源,Android 还是 iOS 中提供的 Webview 底层都支持 WebKit 远程调试协议的,协议的统一是 Web 调试工作的福音,借助现有的 devtools 工具就能够完成 inspector 的功能。

$ ios_webkit_debug_proxy -f chrome-devtools://devtools/bundled/inspector.html

或打开 chrome://inspect/#devices 浏览器调试界面就可以找到 Webview 的页面了。



欢迎讨论,互相学习。

微博: http://weibo.com/xudafeng
Github: https://github.com/xudafeng

下一篇 - Macaca 计算机视觉实现原理

共收到 10 条回复 时间 点赞
达峰的夏天 [公告] Macaca 技术开放计划 中提及了此贴 06月03日 23:27
达峰的夏天 Macaca App Inspector 2.0 发布 中提及了此贴 06月03日 23:27
达峰的夏天 Macaca2.0 升级公告 中提及了此贴 06月03日 23:27
达峰的夏天 [公告] App Inspector 重磅升级 中提及了此贴 06月03日 23:27
思寒_seveniruby 将本帖设为了精华贴 06月04日 01:10
达峰的夏天 Macaca 计算机视觉实现原理 中提及了此贴 06月04日 13:51

达书记,冒昧问下 android 跟 ios 的底层都是通过 UI Automator 实现的吗?

我记得 appium1.6.* 之后 ios 是不是用的 XCTest?望解疑

@haifushi 多谢指正,iOS 端是 XCTest 获取的,不是 UI Automator

👍 最近在学习 macaca,以后有疑问望不吝赐教😂

许伟栋 回复

没问题

苏爱晴 Macaca App Inspector 2.0 发布 中提及了此贴 08月10日 10:36

请问下 bounds 那块怎么解读呀?

匿名 #16 · 2017年11月29日

我有个小问题,做安卓游戏自动化测试的时候,定位到的元素总是很少,有些时候一大片控件会定位为同一个元素。考虑到开发不能给予支持,这要怎么处理比较好?

游戏基于 view 控件体系的吧,尝试 https://macacajs.com/zh/computer-vision

匿名 #18 · 2017年11月29日

游戏是 cocos 引擎的,是不是基于 view 控件体系我也不清楚。感觉 macaca 如果要做自动化测试需要开发进行配合啊

匿名 #19 · 2017年11月29日

不一样啊,我的情况是所有控件都被放在同一个元素内,根本区分不开来,opencv 好像不行

图上面元素只有两个,实际上游戏内部控件很多,全部被放在 android.view.View 里面了

Macaca Inspector 升级 2.0.15 https://testerhome.com/topics/12419

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册