UI 自动化测试应用与实践

一、知识梳理

  • 单元测试: 单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。(开源框架常用)
  • 集成测试: 在单元测试的基础上,将所有模块按照设计要求组装成为子系统或系统,进行集成测试。
  • 验收测试: α测试 === development β测试 === preview γ测试 === production。
  • 白盒测试:又称结构测试、透明盒测试,测试方法有代码检查法、静态结构分析法。(TS、Eslint、Sonar)
  • 黑盒测试:又称功能测试,再不考虑内部结构的前提下测试产品功能。(测试组:80%)
  • 静态测试: 通过分析软件的代码、设计、文档和配置而不执行软件来测试软件的过程。(接口测试)
  • 动态测试: 使用各种输入和场景执行软件并检查其行为和输出来测试软件的过程。(UI 测试)

二、UI 自动化测试 - 意义

  • 它可以帮助我们提高软件质量、减少人工测试的工作量,提高测试效率。
  • 通过自动化测试,我们可以快速、准确地检测软件界面的各种功能和交互,发现潜在的问题和缺陷,确保软件在不同环境下的稳定性和一致性。
  • UI自动化测试还可以提供可靠的回归测试,确保软件在不断迭代更新中不会引入新的问题。总之,UI自动化测试是保障软件质量和用户体验的重要手段,对于提高开发效率和降低风险非常有帮助。

三、UI 自动化测试 - 三板斧

名称 简介 应用解读
Selenium Selenium 是最受欢迎的UI自动化测试框架之一,支持多种编程语言,如Java、Python和C#。它可以模拟用户在网页上的操作,执行各种测试任务。 Appium 目标的一个子集,Selenium 与各个 Web 浏览器供应商和W3C 标准组织合作,将其 API 变成了官方的 Web 浏览器标准,称为WebDriver 规范。
Appium Appium是一个开源的UI自动化测试框架,专门用于移动应用程序的测试。它支持多种移动平台,如iOS和Android,并提供跨平台的测试能力。 基于WebDriver 规范打造统一平台化能力,不仅仅支持iOS 和 Android,Appium 希望支持用户交互从 Web 到移动设备或从 Web 到电视不同的情况,提供了驱动的概念。
Cypress Cypress是一个现代化的JavaScript前端测试框架,旨在对Web应用程序进行端到端的自动化测试。它具有简单易用的API和强大的调试功能。 Cypress 不是基于 WebDriver 开发的,Cypress 使用自己的架构和协议来直接与浏览器交互,而不是通过 WebDriver 接口,Cypress 更适合用于前端端到端测试,而 WebDriver/Selenium WebDriver 更适合用于跨浏览器和跨平台的 Web 应用程序测试。

下图来源于 Appium:

三、UI Automator

UI Automator 测试框架提供了一组 API,用于构建在用户应用和系统应用上执行交互的界面测试。通过 UI Automator API。

# uiautomatorviewer bash 位置
cd ~/Library/Android/sdk/tools/bin

1. uiautomatorviewer-xx.x.x-dev.jar
/Library/Android/sdk/tools/lib
#!/bin/bash
1. 1. Copyright 2012, The Android Open Source Project
1. 1. Licensed under the Apache License, Version 2.0 (the "License");
1. you may not use this file except in compliance with the License.
1. You may obtain a copy of the License at
1. 1.     http://www.apache.org/licenses/LICENSE-2.0
1. 1. Unless required by applicable law or agreed to in writing, software
1. distributed under the License is distributed on an "AS IS" BASIS,
1. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1. See the License for the specific language governing permissions and
1. limitations under the License.

1. Set up prog to be the path of this script, including following symlinks,
1. and set up progdir to be the fully-qualified pathname of its directory.
prog=" $0"
while [ -h "${prog}" ]; do
    newProg=`/bin/ls -ld "${prog}"`
    newProg=`expr "${newProg}" : ".* -> (.*)$"`
    if expr "x${newProg}" : 'x/' >/dev/null; then
        prog="${newProg}"
    else
        progdir=`dirname "${prog}"`
        prog="${progdir}/${newProg}"
    fi
done
oldwd=`pwd`
progdir=`dirname "${prog}"`
progname=`basename "${prog}"`
cd "${progdir}/.."
progdir=`pwd`
prog="${progdir}"/bin/"${progname}"
cd "${oldwd}"

jarfile=`basename $APP_HOME/lib/uiautomatorviewer-26.0.0-dev.jar`
frameworkdir="$progdir"
libdir="$progdir"
if [ ! -r "$frameworkdir/$jarfile" ]
then
    frameworkdir=`dirname "$progdir"`/tools/lib
    libdir=`dirname "$progdir"`/tools/lib
fi
if [ ! -r "$frameworkdir/$jarfile" ]
then
    frameworkdir=`dirname "$progdir"`/framework
    libdir=`dirname "$progdir"`/lib
fi
if [ ! -r "$frameworkdir/$jarfile" ]
then
    echo "${progname}: can't find $jarfile"
    exit 1
fi

javaCmd="java"

os=`uname`
if [ $os == 'Darwin' ]; then
  javaOpts="-Xmx1600M -XstartOnFirstThread"
else
  javaOpts="-Xmx1600M"
fi

if [ `uname` = "Linux" ]; then
    export GDK_NATIVE_WINDOWS=true
fi

while expr "x $1" : 'x-J' >/dev/null; do
    opt=`expr "x $1" : 'x-J(.*)'`
    javaOpts="${javaOpts} -${opt}"
    shift
done

jarpath="$frameworkdir/$jarfile"

1. Figure out the path to the swt.jar for the current architecture.
1. if ANDROID_SWT is defined, then just use this.
1. else, if running in the Android source tree, then look for the correct swt folder in prebuilt
1. else, look for the correct swt folder in the SDK under tools/lib/
swtpath=""
if [ -n "$ANDROID_SWT" ]; then
    swtpath="$ANDROID_SWT"
else
    vmarch=`"${progdir}"/bin/archquery`
    if [ -n "$ANDROID_BUILD_TOP" ]; then
        osname=`uname -s | tr A-Z a-z`
        swtpath="${ANDROID_BUILD_TOP}/prebuilts/tools/${osname}-${vmarch}/swt"
    else
        swtpath="${frameworkdir}/${vmarch}"
    fi
fi

1. Combine the swtpath and the framework dir path.
if [ -d "$swtpath" ]; then
    frameworkdir="${swtpath}:${frameworkdir}"
    1. frameworkdir="${frameworkdir}"
else
    echo "SWT folder '${swtpath}' does not exist."
    echo "Please export ANDROID_SWT to point to the folder containing swt.jar for your platform."
    exit 1
fi

echo "${javaCmd}" $javaOpts -classpath="$frameworkdir" -Dcom.android.uiautomator.bindir="$progdir" -jar "$jarpath" " $@ "

exec "${javaCmd}" $javaOpts -classpath="$frameworkdir" -Dcom.android.uiautomator.bindir="$progdir" -jar "$jarpath" " $@ "

四、uiautomator2

UiAutomator 是Google提供的用来做安卓自动化测试的一个Java库,功能很强,可以对第三方App进行测试,获取屏幕上任意一个APP的任意一个控件属性,并对其进行任意操作。但有两个缺点:

  • 测试脚本只能使用Java语言;
  • 测试脚本要打包成 jar 或者 apk 包上传到设备上才能运行;
  • 改进方案: 在手机上运行了一个 HTTP ****PRC 服务,将uiautomator中的功能开放出来,然后再将这些http接口封装成Python库。

    整体过程:

  • 在移动设备上安装atx-agent(守护进程), 随后atx-agent启动uiautomator2服务(默认7912端口)进行监听;
  • 在PC上编写测试脚本并执行(相当于发送HTTP请求到移动设备的server端);
  • 移动设备通过WIFI或USB接收到PC上发来的HTTP请求,执行制定的操作;
  • 五、业务实践

    业务痛点:

  • 搜索业务 UI 需要兼容pad、折叠屏、手机,每一次迭代,都会有 UI 上的心智负担。
  • UI 自动化测试学习成本较高,需要了解 jdk 环境兼容、ADB 相关的知识储备。
  • 开发与测试协作边界模糊,开发缺少周密的测试用例,测试免去配置复杂的环境。
  • 工具答疑:

  • 问:测试同学已经有了框架,我们在做是不是重复造轮子?

       扩展插件不是为了取代测试已有的测试体系,而是为了打开前端介入参与的大门。提供了转义层,通过可配置的方式实现脚本的转化,这样不仅不会干扰整个测试的体系,反而会促进测试用例的转化。

  • 问:真实的使用方是谁?不用vscode怎么办?
  • 插件扩展是具有针对性的,目前受众是前端。当然,不排除后面服务端、客户端参与进来,也同样会出针对idea相关的插件。

    插件核心是【转化】,当把这部分完善好提炼出来,它就不会局限于插件本身了。就像vue template 转化成 js bundle 的时候,依赖的是 @vue/compiler-core 一样的道理。

  • 问:如何控制测试范围,怎么去修改,后期如何规划?
  • 理想情况下,测试现有的工程可以划分来看,运行环境 + 脚本,运行环境实际上可以保持不变,脚本可以共同来维护,前端可以转化生成脚本,脚本也可以逆转成前端结构,这一点就是构建DSL的思想。