Selemium 和 Appium 是知名的自动化测试框架。其中 Selemium 用于自动化网页测试,而 Appium 则专长于自动化 App 测试。两者可以使用语法相似的 API。相比于 Selemium,Appium 的配置更复杂一些。本文简要介绍 Appium 的开发环境搭建和入门使用方法。选取的是 Android App 的测试,使用的编程语言是 Python。

自动化测试可以应用于多种场景。例如使用 Selemium 编写网络爬虫,可以克服服务器端对 robot 的限制,还可以破解验证码,模拟人工操作等。使用 Appium 操控 App,也可以完成很多机械性的操作任务。具体用途读者可以自由畅想。

下面主要介绍开发环境的配置和一些主要问题的解答。

Appium 开发环境配置

安装 Android 模拟器

如果您是 App 开发人员,那么应该已经有了 Android Studio 自带的 Android 模拟器。如果只是用于测试 App,没有安装 Android Studio 的话,我推荐一个很好用又小巧的 Android 模拟器:网易 MuMu 模拟器,同时支持 Windows 和 MacOS,比 Android Studio 小很多,而且功能很强大。

除了用电脑端模拟器外,开发者也可以用手机连接至电脑,直接对手机进行控制。

下载安装 Appium Desktop

Appium 既可以通过脚本运行,也可以通过 Desktop 程序运行。因为 Desktop 程序的可视化比较强,而且支持直接探查 App 中的元素信息,还可以测试元素定位,所以推荐从 Desktop 入手,一边探查元素,一边编写脚本。Appium Desktop 可以在这里下载。下载后正常安装即可。

启动 Appium 服务

Appium 是一个 Restful API 服务,在自动测试过程中要一直开启 Appium 服务。

打开 Appium Desktop,会弹出启动服务器页面。一共有三种启动服务器的模式,分别是简单模式、高级模式和自定义模式。启动服务器时可以输入很多配置参数,这里暂时不作详细的介绍了。详细的使用说明在这里可以找到。其中有几个我认为比较重要的参数,主要是 chromedriver-executable ,它用于指定调试 WebView 用的 ChromeDriver 的位置。后面会详细提到。现在我们使用简单模式,用默认的 IP 地址和端口启动 Appium。点击 Start server 按钮,服务启动。可以看到界面中显示 The server is running 提示信息。

连接 Android 模拟器

我们先启动 Android 模拟器。双击 网易Mumu模拟器 ,进入 Android 桌面。然后使用应用中心,或者导入 apk,安装要测试的 App。

下一步是到模拟器的安装目录(一般命名为 Nemu )中,在 vmonitor/bin 目录下找到 adb-server ,它是一个可执行程序。把它重命名为 adb ,并把所在路径加入环境变量 PATH 中。打开 cmd,输入 adb,会出现 adb 的使用帮助。这时 adb 配置完成。

下面使用 adb 连接 Android 模拟器。网易Mumu模拟器 的 IP 地址是 127.0.0.1:7555 。在 cmd 中输入以下代码

1
2
3
adb kill-server
adb server
adb connect 127.0.0.1:7555

收到提示:Connected to 127.0.0.1:7555,说明连接成功。

定义 Capabilities

现在我们启动了 Appium 和 adb 两个服务,并启动了 Android 模拟器。下面我们要取得对 App 的控制,也就是开启一个 Session。为了开启 Session,要配置一些参数,Appium 把这些参数取名为 Capabilities。这些 Capabilities 主要定义了模拟器是什么,要控制的 App 是什么,以及控制过程中的一些参数。全部参数定义的文档可以在这里找到。下面介绍几个必须定义的参数和几个值得注意的参数。

  • platform ,这里设为 Android
  • platformVersion ,可以在 Android 模拟器中找到。为模拟器中的 Android 版本。如: 6.0.1
  • deviceName ,网易 Mumu 的 device name 为 127.0.0.1:7555
  • appPackage , 调试 App 的名称。类似 cn.xxxx.android
  • appActivity ,要调试的 App Activity,类似 cn.xxxx.android.yyy.zzz...
  • unicodeKeyboardresetKeyboard ,者设为 true ,可以支持输入中文。
  • newCommandTimeout ,可以设为一个较大的数。否则隔一段时间不执行命令的话,会自动退出。

以上就是以个常用的 Capability。下面简单说说如何获取 App 的名称和 Activity。

获取 App 名称和 Activity

在这里,我们通过 adb 来获得 App 的名称和 Activity。

首先,在模拟器中启动 App。然后再打开一个 cmd 窗口,键入

1
adb shell dumpsys activity |find "mFocusedActivity"

会找到一个字符串,以空格分隔,其中有一段有一个斜杠 / ,斜杠前面就是包名,斜杠后面就是当前 Activity 的名称。这个 Activity 可以打开主屏幕,但是如果要调试加载画面,要找到之前的 Activity。可以打开 adb shell logcat 后启动 App,然后在生成的大量 log 里面查找。一般是不需要的。

启动 Session 并开始调试

设置好 Capabilities 后,Android 模拟器退出 App,回到主界面,点击 Start session 按钮,可以看到,Session 启动,模拟器自动打开了设置的 App 主界面。Appium Desktop 跳转到了调试器。工具栏中有一些常用工具,主界面分成三栏,左边是模拟器截屏,中间是组件的层次关系,右面是选定组件的属性。在左边的点击 App 中的元素,或在中间点击一个组件,后面就会显示出所有属性。

至此,Appium 的环境搭建好了,可以开始进行 App 调试。

使用 Appium 进行 Android App 自动测试

原生 App,WebApp 和 Hybrid App

在 Android App 开发时,可以选择使用原生 App,也就是把页面元素定义为 Android 组件,也可以选择使用 WebView,也就是把 App 看成是一个浏览器,呈现的是 Web 页面。更常用的做法是 Hybrid,也就是有一些元素,比如底部按钮,是原生 Android 组件,而上部采用 WebView 实现内容的快速更新。

由于原生 App 和 WebView 的调试方法不同,我们需要判断 App 是哪种类型,方法很简单。选中要查看的元素,看中间一栏中的层级关系,如果它的名字是 android.widget.xxx ,则是原生的。如果名字里面包含 webview ,那么这一部分就是基于 Web 的。

使用 UiSelector 选取原生元素

UiSelector 是 Android 提供的元素选择器,通过其语法,可以选取任何想要的元素。例如,选取文字为“Hello, world!”的元素。在工具栏中找到放大镜图标,在弹出菜单的 Strategy 中选择 UIAutomator Selector,输入 new UiSelector().text("Hello, world!") ,或者简写为 text("Hello, world!") ,点击 Search 可以看到,文字为“Hello, world!”的元素被列举了出来。UiSelector 选择器功能强大,有很多种选择的方式,可以在这里找到它的详细用法。一个建议是从右栏的属性中找到元素的特点进行选取。

使用 Chrome 选取 WebView 中的元素

对于 WebView 的调试,我们通过 Chrome 浏览器来完成。

在模拟器中打开有 WebView 的页面,然后切换到 Chrome 浏览器,在地址栏中输入 chrome://inspect ,会出现 remote devices 的列表。在里面可以看到 MuMu 一项,就是我们的模拟器了。模拟器的当前页面中加载了的 WebView 都会列在其中。在其中一个下面点击 inspect ,进入调试页面,可以看到 WebView 的内容在 Chrome 中显示了出来。这时我们可以在 console 中使用 javascript 和 css selector 等对 WebView 进行元素选取。

操作元素

选取到了元素后,可以对元素进行控制操作。常见的就是点击和输入。选择元素后,在右侧栏中会出现三个按钮,前两个分别用于点击和键盘输入。

另外,Android 还有一个功能是回退,可以在工具栏中找到一个向后箭头的图标。还有一些滑动操作都可以通过工具栏的按钮完成。

录制操作过挰

读到这里,可能读者会问,上面的操作和人工操作没有什么区别,怎么实现自动控制呢?现在我们就把人工操作的过程录制成代码,这样就可以实现自动操作了。

在工具栏中有一个“眼睛”图标,点开它,就会出现 Recorder 对话框。在下拉菜单中选择你熟悉的语言,比如 Node.js 或 Python,再进行元素选择、点击等操作,会发现每一步操作都被录制下来了。比如说,上述选取“Hello, world!”的操作,在 python 中被翻译成

1
els1 = driver.find_elements_by_AndroidUIAutomator("text(\"Hello, world!\")")

而在 Node.js 的 Webdriver.io 版中被翻译成

1
driver.init().elements('android=text("Hello, world!")');

代码没有用单引号,美观性略逊,稍加改动即可。这些录制的代码可以大大减少我们下一步编写代码的工作量。

到这里,使用 Appium Desktop 来对 App 进行操作就介绍完了。下面我们来写代码,实现全自动的控制。

使用 Python client 调用 Appium

Appium 本身是一个 Restful API,而这个 API 又支持通过多种语言来调用。每种语言就是一种 client。所有支持的语言的列表可以在这里找到。每种语言的安装方式都不同,这里我们只介绍使用 python 来安装 appium-python-client。方法很简单,打开 cmd,输入

1
pip install Appium-Python-Client

就自动安装好了。下面我们来看如何用代码来完成上面的操作。

使用原生 App driver

输入以下代码

1
2
3
4
5
6
7
8
9
10
11
12
from appium import webdriver

desired_caps = {}
desired_caps['platform'] = 'Android'
desired_caps['platformVersion'] = '6.0.1'
desired_caps['automationName'] = 'uiautomator2'
desired_caps['deviceName'] = '127.0.0.1:7555'
desired_caps['appPackage'] = 'cn.xxxx.android'
desired_caps['appActivity'] = 'cn.xxxx.android.yyy.zzz'


driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

通过这种方式,初始化了一个 driver,并在 driver 中定义好了一些 Capabilities。下一步我们进行选择和单击的操作。这里可以把录制的内容搬运过来。不过,有一些函数名进行了重构,所以要作一些修改。

1
2
3
el1 = driver.find_element_by_android_uiautomator('new UiSelector().text("Hello, world!")')
assert el1 is not None
TouchAction(driver).tap(el1).perform()

注意,UiSelector 中 selector 里面要用双引号。最后,退出控制

1
driver.quit()

把以上代码放到一个文件 app.py 中。这只是两个示例用法。更多操作可以参考文档

使用 chromedriver

在调试 WebView 时,要使用 Chromedriver 来驱动。这时,我们把原生 driver 切换到 chromedriver。首先查看是否有 WebView

1
print(self.driver.contexts)

如果有,并且出现在最后一个,则可以使用

1
2
os.system('taskkill /f /im chromedriver.exe')
driver.switch_to.context(self.driver.contexts[-1])

这里有一点需要注意,如果已经有 Chromedriver 在运行,会发生冲突,所以在切换 driver 之前把正在运行的 Chromedriver 进程杀掉。

然后就可以使用 css selector 了

1
els1 = driver.find_elements_by_css_selector(".class-name")

Chromedrier 的使用方法与 Selemium 是一致的,可以参考这篇文档

下载 Chromedriver

Chromedriver 需要单独下载。而且根据 App 中使用 WebView 内核版本的不同,需要使用的 Chromedriver 的版本也不同。此时需要下载特定版本的 chromedriver。可以在这里找到相关的帮助。

运行自动化脚本

保存好了脚本文件后,可以开始运行了。

首先,启到 Appium 服务器。这里介绍一种除了使用 Appium Desktop 之外,从命令行启动 Appium 的工具。它是一个 Node.js 工具,先要在系统中安装Node.js。然后在命令行中通过 npm 来安装

1
npm install -g appium

这样 appium 就安装好了。下面我们启动 appium 服务。在命令行中输入

1
appium --chromedriver-executable path\to\chromedriver.exe

注意这里指定了一个参数,指定了 Chromedriver 的位置。如果端口有冲突,还要指定端口。执行命令,可以看到提示服务器已经启动。这时最小化窗口,不要关闭。另打开一个 cmd,输入

1
python app.py

自动化测试就开始运行了。

本文介绍了使用 Appium,通过 Python 作为 Client,自动化调试 Android App 的基本方法。并在文中列举了文档的位置,希望对读者有所帮助。