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

无意引起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个步骤难办、心中一万匹马)

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