除了标准的W3C API
接口,Uiautomator2
还提供了一系列扩展接口来支持Android
平台相关的操作。本文所有测试代码的前提是已经安装Appium
和相关环境(例如JDK
、Android SDK
、AVD
模拟器),可以参考Appium
环境搭建。
文件管理
1 传输文件到被测设备
接口参数说明:
参数名称 | 参数类型 | 参数是否必须提供 | 描述 | 举例说明 |
---|---|---|---|---|
remotePath |
string |
yes |
文件存储到被测设备上的全路径,如果被测设备的文件已经存在,会覆盖已经存在的文件。 | /sdcard/foo.bar |
payload |
string |
yes |
待传输文件内容,使用Base64 编码。(Python 的webdriver 提供的push_file 接口可以直接指定待传输文件的全路径。) |
QXBwaXVt |
举例:(假定待传输文件为/tmp/file_test
)
# -*- coding: utf-8 -*-
import pytest
import base64
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.appium_service import AppiumService
# 开启服务端
APPIUM_HOST = '127.0.0.1'
APPIUM_PORT = 4723
@pytest.fixture(scope="session")
def start_appium_service():
server = AppiumService()
server.start(args=['--address', APPIUM_HOST, '-p', str(APPIUM_PORT)], timeout_ms=60000)
yield server
server.stop()
# 创建客户端到服务端的会话
def create_appium_session_by_api(custom_opts = None, appium_host = APPIUM_HOST, appium_port = APPIUM_PORT):
options = UiAutomator2Options()
if custom_opts is not None:
options.load_capabilities(custom_opts)
return webdriver.Remote(f'http://{appium_host}:{appium_port}', options=options)
# !发送文件到被测设备
def test_push_file(start_appium_service):
custom_opts = {
"appium:avd": "testPhone",
}
driver = create_appium_session_by_api(custom_opts)
# 直接指定待传输文件的本地路径
driver.push_file(destination_path="/sdcard/file_test", source_path="/tmp/file_test")
# 通过base64编码后进行传输
binary_data = 'hello android'.encode('utf-8')
driver.push_file(destination_path="/sdcard/file_test_base64", base64data=f"{base64.b64encode(binary_data).decode('utf-8')}")
driver.quit()
在被测设备下,可以看到文件已经传输成功。
2 从被测设备获取文件
接口参数说明:
参数名称 | 参数类型 | 参数是否必须提供 | 描述 | 举例说明 |
---|---|---|---|---|
remotePath |
string |
yes |
被测设备上文件的全路径,如果被测设备的文件不存在,会抛出异常。 | /sdcard/foo.bar |
接口调用会返回文件内容,基于Base64
的编码。
# !获取被测设备上的文件
def test_pull_file(start_appium_service):
custom_opts = {
"appium:avd": "testPhone",
}
driver = create_appium_session_by_api(custom_opts)
data = 'hello android'
driver.push_file(destination_path="/sdcard/file_test_base64", base64data=f"{base64.b64encode(data.encode('utf-8')).decode('utf-8')}")
# 读取被测设备上文件
base64_content = driver.pull_file("/sdcard/file_test_base64")
assert (base64.b64decode(base64_content)).decode('utf-8') == data
driver.quit()
3 从被测设备获取文件夹
接口参数说明:
参数名称 | 参数类型 | 参数是否必须提供 | 描述 | 举例说明 |
---|---|---|---|---|
remotePath |
string |
yes |
被测设备上文件夹的全路径,如果被测设备的文件不存在,会抛出异常。 | /sdcard/folder/ |
接口调用会返回文件夹zip
压缩后内容,并基于Base64
的编码。因此下面的例子,在获取到内容后,首先要使用base64
进行内容还原,然后将还原的数据流存到文件中,并使用zipfile
库来解压zip
格式的压缩包。
# !获取被测设备上的文件夹
def test_pull_folder(start_appium_service):
custom_opts = {
"appium:avd": "testPhone",
}
driver = create_appium_session_by_api(custom_opts)
data = 'hello android'
driver.push_file(destination_path="/sdcard/Download/file_test_base64", base64data=f"{base64.b64encode(data.encode('utf-8')).decode('utf-8')}")
# 读取被测设备上文件夹
base64_zip_folder_content = driver.pull_folder("/sdcard/Download/")
# 解析base64的内容,并存储成文件
zip_folder_content = (base64.b64decode(base64_zip_folder_content))
with open("/tmp/test.zip", "wb") as f:
f.write(zip_folder_content)
# 解压文件夹
with zipfile.ZipFile("/tmp/test.zip", 'r') as zip_f:
zip_f.extractall("/tmp")
assert os.path.exists("/tmp/Download/file_test_base64")
file_content = ""
with open("/tmp/Download/file_test_base64") as f:
file_content = f.read()
assert file_content == data
driver.quit()
网友评论