在做自动化测试时,会进行iOS设备的资源操作,常用的“ios-deploy”命令依赖xcode环境,并且可用性差;阿里开源了一个叫做tidevice的工具替代,但是只能实现单个文件的push和pull操作,对于目录级别支持不好,以下使用python进行简单封装,方便直接使用:
import os
import shutil
import subprocess
def adb_shell(cmd):
logger.info(cmd)
output = subprocess.getoutput(cmd)
logger.info(output)
return output
""" 使用tidevice进行iOS相关文件操作 """
# 清除iOS设备整个文件夹所有内容
def ios_clear_path(device_id, bundle_id, path):
adb_shell('tidevice -u {} fsync -B {} rmtree {}'.format(device_id, bundle_id, path))
# 从本地往iOS设备push文件,支持整个目录到目录,使用示例:utils.ios_push_files(serialno, pkg_name, 'tmp/testdir1', 'Documents/res')
def ios_push_files(device_id, bundle_id, local_path, device_path):
local_file_pre_list = []
local_file_list = get_filelist_and_pre(local_path, '', [], local_file_pre_list)
local_file_pre_list = list(set(local_file_pre_list))
if len(local_file_list) > 0:
for pre in local_file_pre_list:
device_pre = pre.replace(local_path, device_path, 1)
if not device_pre.find('__MACOSX') > 0:
adb_shell('tidevice -u {} fsync -B {} mkdir {}'.format(device_id, bundle_id, device_pre))
device_file_list = []
for file in local_file_list:
file_device = file
file_device = file_device.replace(local_path, device_path, 1)
device_file_list.append(file_device)
for index in range(len(local_file_list)):
if not local_file_list[index].endswith('.DS_Store') and not local_file_list[index].find('__MACOSX') > 0:
adb_shell('tidevice -u {} fsync -B {} push {} {}'.format(device_id, bundle_id, local_file_list[index], device_file_list[index]))
# 从iOS设备往本地pull文件,支持整个目录到目录(有个缺陷,本地将不含设备中的子目录,而是将所有文件放到一个目录下),使用示例:utils.ios_pull_files(serialno, pkg_name, 'Documents/', 'tmp/test_ios_pull/')
def ios_pull_files(device_id, bundle_id, device_path, local_path):
no_pre_file_list = []
files_list = ios_recursively_get_file_list(device_id, bundle_id, device_path, no_pre_file_list)
logger.info('ios_pull_files no_pre_file_list: {}'.format(no_pre_file_list))
if len(files_list) > 0 :
if not os.path.exists(local_path):
os.makedirs(local_path)
for file in files_list:
# if file != '.DS_Store':
adb_shell('tidevice -u {} fsync -B {} pull {}'.format(device_id, bundle_id, file))
for file in no_pre_file_list:
shutil.move(file, local_path + '/')
# 递归获取iOS设备文件夹里所有文件,返回的result_file_list会带具体目录前缀,no_pre_file_list不带前缀
def ios_recursively_get_file_list(device_id, bundle_id, path, no_pre_file_list):
# adb_shell('tidevice -u {} fsync -B {} tree {}'.format(device_id, bundle_id, path))
result_file_list = []
files_list = []
files_list_txt = adb_shell('tidevice -u {} fsync -B {} ls {}'.format(device_id, bundle_id, path))
if files_list_txt and files_list_txt != '[\'\']' :
files_list = eval(files_list_txt)
for file in files_list:
tmp_no_pre_file_list = []
inner_list = ios_recursively_get_file_list(device_id, bundle_id, path + '/' + file, tmp_no_pre_file_list)
if len(inner_list) > 0:
for file_inn in inner_list:
result_file_list.append(file_inn)
for file_no_pre in tmp_no_pre_file_list:
no_pre_file_list.append(file_no_pre)
else:
result_file_list.append(path + '/' + file)
no_pre_file_list.append(file)
return result_file_list