UiAutomator 桌面程序如何做 UI 测试自动化

怀沙 · 2019年08月02日 · 最后由 怀沙 回复于 2021年08月13日 · 8494 次阅读

无意引起UI 自动化是否必要的争论、所以想讨论这个问题朋友可以单独开一篇帖子
文笔不好、为了尽量写得通俗易懂、文中可能有的地方比较啰嗦、请见谅。
深知不可能用一篇文章就把一种技术讲得清晰明了、所以文章里面写得内容都是比较简单的解决方案;
如果某一天在做自动化时、发现现有的方案实现不了的时候、想起来之前谁谁谁有分享过其他解决方案、我的目的就达成了!

内容有点多、请提前做好准备

UI 测试自动化分类

UI 测试自动化大致可以分为下面几种情形

  • B/S 架构的 Web UI 测试自动化
  • APP 测试自动化
  • C/S 架构的 UI 测试自动化

不管你使用什么技术来执行测试自动化至少都得包含如下几个步骤

  • 1、找
    • 找元素、控件、输入框、等等一切你想找的内容
  • 2、控制
    • 单击、双击、输入内容、下拉等等一系列操作属于控制的范畴
  • 3、断言
    • 断言就不用解释了把

为什么要写这篇文章

1. 如果我们是做 Web UI 自动化、现成的框架有 Selenium 和 Robot Framework 可以选择
2. 如果你是 APP 自动化、有 Appium 可以选择
3. 如果 C/S 的程序是 Windows 标准控件的话、可以用 MSAA 或者 UIA 来做自动化
4. 如果上述技术解决方案都解决不了的时候、我们又想实现测试自动化要怎么办?这是我写这篇文章的原因、所以我把文章取名叫 “UI 测试自动化的奇技淫巧”

那么接下来我准备从三个方面来分享一下我在 UI 测试自动化中的一些理解、和大家一起探讨。

一:坐标方案

当屏幕上有按钮图标时、那么这个图标必然会处于某一个坐标之上;也就是说只要点击目标相应位置的坐标就能点击到图标。
输入内容、滑动、下拉等等一系列操作的前提是需要先找到目标位置。

先简单介绍一下坐标的概念;这里我们说的坐标是屏幕坐标

  1. 坐标用距离窗口左上角的水平距离和垂直距离来指定对象的位置
  2. 坐标的 X 轴向右为正,Y 轴向下为正
  3. 坐标原点位于窗口的左上角

如何取坐标值

一般情况下你使用 QQ 截图即可完成对目标坐标的获取。

上面的图片中我用截图工具来丈量了 “用户名输入框的坐标位置 (712,183)
我们只要使用MoveTo(712,183)这样的命令即可把鼠标移动到输入框上

使用坐标实现的一个自动登录用例

import pyautogui
import time
#用户名输入框
pyautogui.moveTo(712,183)
pyautogui.click()
pyautogui.typewrite("huang")
time.sleep(3)
#密码输入框
pyautogui.moveTo(712,234)
pyautogui.click()
pyautogui.typewrite("11qq1")
#登录按钮
pyautogui.moveTo(712,356)
pyautogui.click()

通过上面这几行代码、用单纯的坐标实现了一个自动化登录的用例、下面我们看一下效果

细心的你应该发现了、坐标是一个固定的值、并且是没有办法断言的、也就是你不知道坐标值下是否有图标;
坐标法 就是人为找到按钮坐标位置、然后模拟鼠标键盘去执行操作

坐标法的优势

  1. 简单;量一下坐标就可以了
  2. 稳定;只要代码里面moveTo没写错、肯定就是把鼠标移动到指定坐标位置

坐标法的劣势

  1. 不能断言;不能判断坐标下面是否有内容、或者是什么内容
  2. 兼容性差;目标程序移动位置、换一台显示器、坐标就不一样了

二:颜色识别方案

在讲颜色识别之前、必须要先简单介绍一下三原色颜色值像素

三原色 (RGB)

我们在显示器上看到的所有色彩都是红绿蓝三种颜色调和而成

颜色值

颜色值用十六进制来表示
每个颜色的最低值为 0(十六进制为 00),最高值为 255(十六进制为 FF)
十六进制值的写法 #FFFFFF

更多关于三原色的信息大家可以自行 Google

像素

像素是视频显示的基本单位、也就是屏幕上的最小单位

给大家一个例子
这是 QQ 的 ICO 图标

然后放大到最大化

图片里面一个一个小方块就是像素;而像素里面又包含了颜色值。

我们终于可以说颜色识别的原理了

  • 通过像素的颜色值在屏幕上找到目标
  • 然后目标坐标值
  • 模拟鼠标键盘进行操作
  • 并通过颜色识别做断言

有了理论基础 我们开始实践

如果你想用颜色识别来做自动化、那么按键精灵大漠插件是目前最好用最稳定的实现方案。
接下来的操作是用大漠插件实现的

  • 用大漠插件工具加载图片
  • 然后取色
  • 当二值化区域能清晰的看到我们要找的目标时、就说明这个颜色值可以在屏幕上找到目标
  • 复制颜色值代码、我们要开始写代码了

下面是代码

#! /usr/bin/env python3
# encoding:utf-8
import time
import pyautogui
import win32com.client
import win32api
# 找登录按钮
login = dm.FindMultiColor(
    0, 0, 1200, 750, "96966d",
    "6|0|d2d38a,0|10|c8c698,9|10|e7da98,16|0|e7da98,17|5|96ac7d,18|10|daac2f",
    0.8, 1)
print("找到登录按钮坐标:", login)
if login[0] > 0:
    intX, intY = login[1:]
    pyautogui.moveTo(intX, intY - 180)  # 输入帐号位置
    pyautogui.click()
    pyautogui.typewrite("17275")
    pyautogui.PAUSE = 0.5

大漠插件颜色识别

其实我们用到的最最主要的就这个方法FindMultiColor()

核心代码就这几行、简单介绍一下步骤

  • 传递区域坐标、多点找色颜色值、匹配度 0.8,查找方向是 1 也就是从左到右,从下到上
  • 判断返回值是否大于 0
  • 返回值如果大于 0 说明通过颜色值找到目标位置
  • 获取坐标位置
  • moveTo()移动鼠标到目标坐标
  • 实现点击操作

执行效果


上面的视频里面有 2 个自动化用例

  1. 自动登录
  2. 兑换一个物品

颜色识别的优势

  1. 可以做断言;这是单纯的坐标法解决不了的痛点
  2. 适应性强;只要你愿意基本上都可以用颜色识别来做自动化;如果不信的可以去按键精灵论坛看下有多少人按键精灵写外挂就知道了;

颜色识别法的劣势

  1. 代码写起来比较麻烦、每一个目标元素都是要单独取色
  2. 如果你的程序有自动换皮肤的功能就麻烦了
  3. 没有用颜色识别的自动化框架;

三: 图像识别方案

说起图像识别、那么 OpenCV 大家必须是需要了解的。

图像识别界的泰斗 OpenCV

  • OpenCV 是什么?
    • 一个跨平台的开源的计算机视觉库
  • OpenCV 能做什么?
    • 人脸识别、手势识别、物体识别、动作识别······

这还不止重点、因为我们重点要知道的是 OpenCV 的模版匹配

OpenCV 模版匹配


上面是我翻译过的 OpenCV 的 6 个模版匹配

模版匹配的用法

简单来说、就是用一张模版图片去源图里面匹配、如果匹配到就返回坐标
当我们拿到坐标之后可以做你想做的事情

OpenCV 模版匹配的简单用法


上面的代码、我们用一张模版图片、在源图里面匹配、然后画一个矩形
代码执行之后的效果如下

如何用图像识别做测试自动化

  • Sikuli;应该是最早使用图像识别来做测试自动化的框架了
  • Airtest; 网易在 18 年开源的基于图像识别的测试自动化框架

这 2 个的底层都是基于 OpenCV 的图像识别;所以我才在前面罗里吧嗦了很久 OpenCV
由于我只会一丢丢的 Python、所以图像识别方案的自动化脚本我用 Airtest 来做的

Airtest 自动化框架

Airtest 是一个跨平台的 UI 自动化测试框架,适用于游戏和 App。目前支持 Windows 和 Android 平台,iOS 支持已经发布

我直接录制了一个小视频、简单易懂

图像识别的优势

  • 会截图就会自动化
  • 测试报告几乎完美

Airtest 不完善的地方

  • 截图也是一个技术活;当你遇到截了 20 多张图、还是定位失败的时候可能要崩溃了
  • 功能还不完善

结束了

当你用SeleniumAppiumMSAA或者UIA常规的自动化解决方案都做不了、
但是还想最自动化的时候、可以来看看我的方案。

我们再来回忆一下 UI 测试自动化三板斧;

    • 找元素、按钮、输入框、控件等等等
    • 怎么找?用坐标、颜色识别、图像识别
  • 控制
    • 单击、双击、输入内容、下拉、滑动等等等
    • 怎么控制? 模拟鼠标键盘
  • 断言
    • 颜色识别
    • 图像识别

未来?

我们在做 UI 测试自动化的时候、最难办的就是断言;(一共就 3 个步骤、有 2 个步骤难办、心中一万匹马)

那么 有没有更好的解决方案?

共收到 26 条回复 时间 点赞

OpenCV 会遇到在不同分辨率手机截图导致模版匹配不上的情况 截图又回变成技术活……

纯稀饭 回复

如果是测试 APP 的话、网易的 airtest 和 poco 可以用一下;通过查找控件、而不是图像识别;

颜色识别那个有启发,点赞👍 ,但是有缺陷基于鼠标,坐标的这种基本上一台机器只能跑一个程序,复用率比较低。之前尝试过 airtest,但是用了之后效果没有到预期。最后还是用了 pywin32 来做了部分自动化,这种 pywin32 的遇到那种嵌入页面的也没什么好的办法,只有注入 js 进去(这种操作有一定的难度,成本比较大)。

怀沙 #23 · 2019年08月06日 Author
快达年 回复

颜色识别那个可以让鼠标后台运行的;这样的话你的电脑可以继续做其他事情了.

Air test 对于 VC 框嵌套 HTML 这种客户端程序支持不太友好、我用颜色识别来做的、成功率还可以;

可以直接把 airtest 识别库拉出来 ,用来识别桌面程序也是可以的。

ChienHsueh 回复

其实 airtest 的图像识别库就是 OpenCV;
你自己也是可以用 OpenCV 来做到 airtest 的功能、可是很麻烦呀;
所以 airtest 给你封装好了、用起来就很方便了;

但是如果你遇到 VC 框嵌套 HTML 内容的程序;用图像识别就比较困难了

最近也在实现桌面应用程序的 UI 自动化,感觉 pyautogui 识别率还是蛮高的。还没遇到定位不到的问题。

jimy 回复

pyautogui 做图像识别、失败率很高呀;
你这边有用到图像识别么

怀沙 回复

有的,使用截图文件进行定位,然后进行点击操作。目前准确率还蛮可以的。

当前市面的缺少的是像 QTP(UFT)/TestComplete 这种支持桌面应用的开源框架。
如果楼主能够把所有的实现整合到一个框架体系下,感觉会很受大家欢迎。加油!!!

终于知道问题所在了,dm 是插件,但是我调用了后是只能用 32 位 pthon 吗

怀沙 #15 · 2019年09月07日 Author
jimy 回复

我之前在测试时用 pyautogui 的时候图像识别非常不好用、所以换其他方式了、抽空在试试新版 pyautogui

怀沙 #10 · 2019年09月10日 Author
混子 回复

你可以用 64 位的操作系统、但是由于 DM 插件是 32 位的、所以你得安装 32 位的 Python 版本

applepen 回复

其实 airtest 已经可以完成以前 QTP 做的功能了

怀沙 #12 · 2019年09月12日 Author
solomon 回复

所有的语言都抵不上这一个 ‘赞’ 字

颜色识别 新思路。

怀沙 #18 · 2019年09月13日 Author
羽寰 回复

其实在外挂领域、按键精灵和大漠插件已经有 10 多年的历史了、只不过我们很少用他来做测试自动化.

jimy 回复

实际项目中你们的案例有多少呢,我这边也想用这个来试下内嵌页 UI 自动化,就是担心稳定的问题,其他还好

做按键精灵的公司现在做了一款 RPA 工具叫做 UiBot

桌面应用程序用的是 delphi 框架里面镶嵌了 c# 写的 h5 页面用什么定位好一点呢

Ranorex Studio 了解一下。

怀沙 #23 · 2021年06月07日 Author
fiskeryang 回复

难怪 按键精灵好多年不更新了😀

怀沙 #24 · 2021年06月07日 Author
付加伟 回复

现在很多桌面程序都是内嵌 H5 了、所以我基本上都是单独吧 H5 页面拿出来用 selenium 跑自动化。

请问支持 mac 吗

怀沙 #26 · 2021年08月13日 Author
Elsie 回复

Python 和 OpenCV 都支持 Mac 的

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