Appium

Appium 是一个开源的自动化测试工具,支持移动应用的自动化测试,特别是原生应用、混合应用和移动网站应用。Appium 提供了跨平台的支持,能够对 iOS 和 Android 平台上的应用进行测试,广泛应用于移动端的自动化测试中。

架构

appium实施原理

  • Appium Server:Appium 服务器是中心组件,接收并处理来自客户端的请求。Appium Server 通过 HTTP 协议与客户端交互,实际执行测试命令。

  • Appium Client:客户端是用户编写测试脚本的地方,测试脚本可以用多种编程语言编写,客户端负责通过 Appium Server 与设备交互。

  • Appium Driver:每个平台(iOS 和 Android)都有不同的驱动程序。Appium 为 iOS 和 Android 提供了独立的驱动程序,分别为:

    • UIAutomator2:用于 Android 平台的驱动程序。
    • XCUITest:用于 iOS 平台的驱动程序。

安装

  1. Appium Server

Appium 是一个基于 Node.js 的工具,因此需要先安装 Node.js。

安装完 Node.js 后,安装服务端。

npm install -g appium
  1. Appium Client

客户端包含多种语言,常用的如 Python、Java、Javascript等等。

Python Appium Client:

pip install Appium-Python-Client

Javascript Appium Client:

npm install --save appium
  1. Appium Inspector

Appium-Inspector 是一个可视化的 Appium 工具,方便开发者定位 App 中的元素,一般用于 Appium v2 版本,兼容 Appium v1 版本。

在 Appium v1 版本中,一般使用的 Appium-Desktop ,它携带了一个启动 Appium Server 的界面,无需手动安装与启动。

功能介绍

  1. 启动应用:可以通过 Appium 启动或安装应用,并在模拟器或真机上执行自动化测试。
  2. UI 元素定位:支持多种方式定位 UI 元素,如基于 XPath、ID、class name、UIAutomator、XCUIElementType 等。
  3. 触摸操作:Appium 支持多种触摸操作,包括点击、长按、滑动、拖动、捏合等。
  4. 应用状态管理:支持启动应用、关闭应用、后台运行应用等操作。
  5. 屏幕截图:支持截图功能,可以获取测试过程中应用的屏幕截图。
  6. 性能监控:通过 Appium 可以执行性能测试,获取设备的 CPU、内存、网络等性能数据。
  7. 同步和异步执行:Appium 支持同步执行和异步执行,可以根据需求调整。

使用

在使用 Appium Client 之前,先启动 Appium Server。

终端输入:

appium --allow-cors

--allow-cors​ :表示允许跨域请求。

Appium 大体使用与 Selenium 一致,Appium 和 Selenium 都是基于 WebDriver 的 API,因此它们共享大多数功能和方法。

启动应用

from appium import webdriver
from time import sleep

# 设置 DesiredCapabilities
desired_caps = {
'platformName': 'Android', # Android 平台
'platformVersion': '10', # Android 版本
'deviceName': '127.0.0.1:5555', # 模拟器/设备名称
'appPackage': 'com.example.app', # 应用的包名
'appActivity': '.MainActivity', # 应用的启动 Activity

'automationName': 'UiAutomator2', # 指定UiAutomator
'noReset': True # 是否保持应用状态
}

# 初始化驱动程序
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

# 示例操作
sleep(5)
driver.quit()

UI元素定位

from appium.webdriver.common.mobileby import MobileBy

driver.find_element(by=MobileBy.ID, value="ele_id")

Appium 没有直接通过显示等待,但是可以配合 Selenium 的显示等待使用。

from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 显示等待
WebDriverWait(driver, 5).until(ec.presence_of_element_located(
(MobileBy.ID, 'ele_id')
)).click()

# 隐式等待
driver.implicitly_wait(5)

触摸操作

  1. 点击。
from appium.webdriver.common.touch_action import TouchAction

action = TouchAction(driver)

# 点击某个元素
action.tap(element).perform()
# 点击某个坐标
action.tap(x=x, y=y).perform()
# 点击某个元素 n 次
action.tap(element, count=n).perform()
  1. 长按。
# 长按某个元素
action.long_press(element).perform()

# 或者长按屏幕的某个坐标(x, y)
action.long_press(x=100, y=200).perform()
  1. 滑动。
# 从坐标 (x1, y1) 滑动到 (x2, y2)
action.press(x=x1, y=y1).move_to(x=x2, y=y2).release().perform()

# 从坐标 (x1, y1) 滑动到 (x2, y2) 使用 n 毫秒
driver.swipe(x1, y1, x2, y2, n)

使用 press​ + move_to​ 可以组合实现多点触摸及缩放等复杂操作。

应用状态管理

可以通过 driver​ 对象调用对应的方法进行应用状态的管理。

方法 描述
launch_app() 启动应用
close_app() 关闭当前应用
reset() 重置应用,重新安装并清除数据
background_app(seconds) 将应用切换到后台并指定后台停留时间
query_app_state() 查询应用的状态:未启动、前台、后台运行、后台暂停等
activate_app() 将应用切换到前台
current_package 获取当前应用的包名
current_activity 获取当前应用的活动名(Activity)
open_settings() 打开设备的设置页面
terminate_app() 强制终止应用(不等同于关闭应用)

截屏录制

可以通过 driver​ 对象调用对应的方法进行截屏图片和录制视频。

方法 描述
get_screenshot_as_file() 获取屏幕截图并保存为文件
get_screenshot_as_base64() 获取屏幕截图并返回 Base64 编码的图片
get_screenshot_as_png() 获取屏幕截图并返回 PNG 格式的二进制数据
start_recording_screen() 开始录制屏幕内容
stop_recording_screen() 停止录制屏幕并返回录制的视频内容(Base64 编码格式)

性能监控

Appium 允许通过 dumpsys​ 与 adb​ 命令获取 Android 设备的系统性能信息。

  1. cpu使用情况。
cpu_usage = driver.execute_script("mobile: shell", {
'command': 'dumpsys cpuinfo'
})
  1. 内存使用情况。
memory_usage = driver.execute_script("mobile: shell", {
'command': 'dumpsys meminfo'
})
  1. 电池使用情况。
battery_status = driver.execute_script("mobile: shell", {
'command': 'dumpsys battery'
})
  1. 网络使用情况。
network_status = driver.execute_script("mobile: shell", {
'command': 'dumpsys netstats'
})