iOS自动化测试工具-tidevice

打印 上一主题 下一主题

主题 781|帖子 781|积分 2343

在iOS测试过程中,经常会需要检察设备udid、检察包名,安装和卸载应用,获取设备截图,获取性能数据等操作,Android有丰富的adb命令可以使用,iOS的tidevice工具就雷同于Android的adb,可以提供这些功能;
一直以来也没有可以或许直接获取iOS性能数据的工具,tidevice可以方便的获取性能数据;
另外,一直以来iOS自动化的执行都依赖于mac体系,主要原因是需要xcode编译安装wda(WebDriverAgent)到ios设备中,通过wda实现对被测应用进行操作,而Windows体系无法运行Xcode,因此无法运行iOS自动化测试;tidevice也解决了这一题目。

一、简介

tidevice是阿里开源的iOS自动化测试工具,可以或许提供截图、获取手机信息、ipa包的安装和卸载、根据bundleID启动和停止应用、获取指定应用性能数据、模拟xcode运行xctest等功能。支持iOS手机的范围是9-16。
https://github.com/alibaba/taobao-iphone-device

二、tidevice的原理

usbmux通信协议:实现 Mac/Windows/Linux与 iOS设备服务间的通信
Mac端:usbmuxd 是苹果的一个服务,这个服务主要用于在USB协议上实现多路TCP毗连,将USB通信抽象为TCP通信,通过建立一个TCP毗连到usbmuxd的/var/run/usbmuxd TCP端口,然后usbmuxd将请求发送到USB毗连的iPhone上。苹果的iTunes、Xcode,都直接或间接地用到了这个服务。
Linux / Windows端:本身是没有 usbmux的,不外都有开源项目标实现,可以直接使用/参考。
Windows 另外依赖 AppleApplicationSupport和AppleMobileDeviceSupport 两个服务,安装Itunes 环境即可安装对应服务。
usbmux 本身是socket套接字,通过截获、破解等手段,联合开源界的结果,用python 进行模拟,从而实现了当前工具已有的所有功能。

三、安装与配置

1.依赖环境

python3.6以上
2.tidevice安装

  1. pip3 install -U "tidevice[openssl]"
复制代码
如果电脑上有多个python3版本,最好指定python版本安装:
  1. 电脑上有python3.9和python3.11,想基于python3.9使用tidevice,所以指定python3.9版本
  2. python3.9 -m pip install -U "tidevice[openssl]"
复制代码
验证安装成功:
  1. $ tidevice version
  2. tidevice version 0.9.12
复制代码
3.usbmux安装



  • Mac 自带:/var/run/usbmux
  • Linux/Windows: 参考官方建议的 tidevice.exceptions.MuxError: socket unix:/var/run/usbmuxd unable to connect · Issue #7 · alibaba/tidevice · GitHub

四、常用命令简介

tidevice是python工程,tidevice 支持的所有cmd 都在tidevice.__main__中界说实现,可对功能重新封装。
  1. #查看更多功能
  2. $ tidevice -h
  3. usage: tidevice [-h] [-v] [-u UDID] [--socket SOCKET] [--trace]
  4.                 {version,list,info,date,sysinfo,appinfo,applist,battery,screenshot,install,uninstall,reboot,shutdown,parse,watch,wait-for-device,launch,energy,kill,ps,relay,xctest,wdaproxy,syslog,fsync,crashreport,dumpfps,developer,pair,unpair,perf,set-assistive-touch,savesslfile,test}
复制代码
1.列出毗连设备

  1. $ tidevice list
  2. UDID                                      SerialNumber    NAME      MarketName     ProductVersion    ConnType
  3. e372ee5092535ad955329aac04c4xxxxx F2LV30FXXX00    iPhone7p  iPhone 7 Plus  13.6.1            usb
复制代码
  1. $ ticevice list --json
  2. [
  3.     {
  4.         "udid": "e372ee5092535ad955329aac04c450fb7xxxx",
  5.         "serial": "F2LV30XXG00",
  6.         "name": "iPhone7p",
  7.         "market_name": "iPhone 7 Plus",
  8.         "product_version": "13.6.1",
  9.         "conn_type": "usb"
  10.     }
  11. ]
复制代码
2.应用管理

(1)安装应用
  1. #安装应用
  2. $ tidevice install example.ipa
复制代码
2)指定设备安装
  1. #指定设备安装
  2. $ tidevice --udid $UDID install  https://example.org/example.ipa
复制代码
(3)卸载应用
  1. #卸载应用
  2. $ tidevice uninstall 包名
  3. Uninstalling 'com.XXX.XXX'
  4. - RemovingApplication (50%)
  5. - GeneratingApplicationMap (90%)
  6. Complete
复制代码
4)启动应用
  1. #启动应用
  2. $ tidevice launch bundleid
  3. PID: 675
复制代码
(5)停止应用
  1. #停止应用
  2. $ tidevice kill bundleid
  3. Kill pid: 675
复制代码
(6)检察已安装的应用
  1. #查看已安装的应用
  2. $ tidevice applist
  3. com.alipay.iphoneclient 支付宝 10.3.70
复制代码
(7)检察运行中的应用
  1. #查看运行中的应用
  2. $ tidevice ps
  3. PID NAME                    BUNDLE_ID                         DISPLAY_NAME           
  4. 733 Preferences             com.apple.Preferences             设置                     
  5. 274 CoreAuthUI              com.apple.CoreAuthUI              用户鉴定                  
  6. 185 Spotlight               com.apple.Spotlight               Siri搜索                 
  7. 416 InCallService           com.apple.InCallService           InCallService                        
  8. 247 AlipayWallet            com.alipay.iphoneclient           支付宝                    
  9. 713 SafariViewService       com.apple.SafariViewService       SafariViewService      
  10. 344 EscrowSecurityAlert                                                              
  11. 748 MobileSafari            com.apple.mobilesafari            Safari浏览器              
  12. 756 iMessageAppsViewService com.apple.iMessageAppsViewService iMessageAppsViewService
  13. #以json格式输出
  14. $ tidevice ps --json
  15. [
  16.     {
  17.         "pid": 733,
  18.         "name": "Preferences",
  19.         "bundle_id": "com.apple.Preferences",
  20.         "display_name": "设置"
  21.     },
  22.     {
  23.         "pid": 274,
  24.         "name": "CoreAuthUI",
  25.         "bundle_id": "com.apple.CoreAuthUI",
  26.         "display_name": "用户鉴定"
  27.     },
  28.     {
  29.         "pid": 185,
  30.         "name": "Spotlight",
  31.         "bundle_id": "com.apple.Spotlight",
  32.         "display_name": "Siri搜索"
  33.     }
  34. ]
复制代码
(8)检察应用信息
  1. $ tidevice appinfo com.example.demo
复制代码
3.检察设备信息

  1. $ tidevice info
  2. MarketName:       iPhone 7 Plus
  3. DeviceName:       iPhone7p
  4. ProductVersion:   13.6.1
  5. ProductType:      iPhone9,2
  6. # 查看设备电源信息
  7. $ tidevice info --domain com.apple.mobile.battery --json
  8. {
  9.     "BatteryCurrentCapacity": 100,
  10.     "BatteryIsCharging": false,
  11.     "ExternalChargeCapable": true,
  12.     "ExternalConnected": true,
  13.     "FullyCharged": true,
  14.     "GasGaugeCapability": true,
  15.     "HasBattery": true
  16. }
复制代码
4.其他常用

(1)重启手机
  1. # 重启
  2. $ tidevice reboot
复制代码
2)截图
  1. # 截图
  2. $ tidevice screenshot xxx.png
复制代码
3)输出日志
  1. # 输出日志 same as idevicesyslog
  2. $ tidevice syslog
复制代码
5.瓦解日志操作

  1. usage: tidevice crashreport [-h] [--list] [--keep] [--clear] [output_directory]
  2. positional arguments:
  3.   output_directory  The output dir to save crash logs synced from device (default: None)
  4. optional arguments:
  5.   -h, --help        show this help message and exit
  6.   --list            list all crash files (default: False)
  7.   --keep            copy but do not remove crash reports from device (default: False)
  8.   --clear           clear crash files (default: False)
复制代码
  1. $ tidevice crashreport --list
  2.   
  3.   [I 230614 16:42:39 _crash:23] List of crash logs
  4. `-- /
  5.     |-- debugserver-2023-06-02-110906.ips
  6.     |-- WeChat-2023-05-30-180918.ips
复制代码

五、性能数据采集

tidevice可以用命令行或者python脚本方式获取性能数据。
1.命令行方式

  1. #命令详解
  2. usage: tidevice perf [-h] -B BUNDLE_ID [-o PERFS]
  3. optional arguments:
  4.   -h, --help            show this help message and exit
  5.   -B BUNDLE_ID, --bundle_id BUNDLE_ID
  6.                         app bundle id (default: None)
  7.   -o PERFS              cpu,memory,fps,network,screenshot. separate by ","
  8.                         (default: None)
复制代码
  1. #获取所有性能数据
  2. $ tidevice perf -B bundleID
  3. fps {'fps': 0, 'value': 0, 'timestamp': 1686732621727}
  4. gpu {'device': 0, 'renderer': 0, 'tiler': 0, 'value': 0, 'timestamp': 1686732621819}
  5. screenshot {'value': <PIL.PngImagePlugin.PngImageFile image mode=RGB size=281x500 at 0x7FCC995CA110>, 'timestamp': 1686732622353}
  6. fps {'fps': 50, 'value': 50, 'timestamp': 1686732622739}
  7. gpu {'device': 0, 'renderer': 0, 'tiler': 0, 'value': 0, 'timestamp': 1686732622829}
复制代码
  1. #获取某一性能指标的数据,eg:memory
  2. $ tidevice perf -B bundleID -o memory
  3. memory {'pid': 287, 'timestamp': 1686732591464, 'value': 236.6890106201172}
  4. memory {'pid': 287, 'timestamp': 1686732592332, 'value': 236.6890106201172}
  5. memory {'pid': 287, 'timestamp': 1686732593323, 'value': 236.6890106201172}
  6. memory {'pid': 287, 'timestamp': 1686732594332, 'value': 236.6108856201172}
  7. memory {'pid': 287, 'timestamp': 1686732595319, 'value': 236.5640106201172}
  8. memory {'pid': 287, 'timestamp': 1686732596327, 'value': 236.5796356201172}
  9. memory {'pid': 287, 'timestamp': 1686732597318, 'value': 236.5952606201172}
复制代码
  1. # 功耗采集
  2. # 每一秒打印一行JSON,至于里面什么单位不太懂
  3. $ tidevice energy com.example.demo
  4. {"energy.overhead": -10.0, "kIDEGaugeSecondsSinceInitialQueryKey": 0, "energy.version": 1, "energy.networkning.overhead": 0, "energy.appstate.cost": 8, "energy.location.overhead": 0, "energy.thermalstate.cost": 0, "energy.networking.cost": 0, "energy.cost": -10.0, "energy.cpu.overhead": 0, "energy.appstate.overhead": 0, "energy.gpu.overhead": 0, "energy.inducedthermalstate.cost": -1}
复制代码
2.python脚本方式

  1. import time
  2. import tidevice
  3. from tidevice._perf import DataType
  4. t = tidevice.Device()
  5. # perf = tidevice.Performance(t,[DataType.CPU, DataType.MEMORY, DataType.NETWORK, DataType.FPS, DataType.PAGE, DataType.SCREENSHOT, DataType.GPU])
  6. perf = tidevice.Performance(t,DataType.MEMORY)
  7. def callback(_type:tidevice.DataType,value:dict):
  8.     print(_type.value,value)
  9. perf.start('com.example.demo',callback = callback)
  10. time.sleep(60)
  11. perf.stop()
复制代码

可以用pyecharts自动天生及时的性能采集报告。
安装pyecharts
  1. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyecharts
复制代码
  1. #绘图
  2. x = [i for i in range(len(d))]
  3. y = d
  4. print(x)
  5. print(y)
  6. #创建对象,可以添加一些参数
  7. line = Line(init_opts=options.InitOpts(width='800px',height='600px'))
  8. #添加x轴y轴数据,注意添加y轴数据的时候必须设置series_name参数,表示图例的名称
  9. line.add_xaxis(xaxis_data=x)
  10. line.add_yaxis(series_name='memory', y_axis=y, is_symbol_show=True, label_opts=options.LabelOpts(is_show=False),
  11.                #is_symbol_show=True显示点,label_opts=opts.LabelOpts(is_show=False)不显示值
  12.                #设置展示最大值最小值
  13.                 markpoint_opts=options.MarkPointOpts(
  14.                     data=[
  15.                         options.MarkPointItem(type_="max",name="最大值", symbol="pin", symbol_size=[70,50]),
  16.                         options.MarkPointItem(type_="min", name="最小值",symbol="pin", symbol_size=[70,50], itemstyle_opts={'color':'#3CB371'}),
  17.                     ]
  18.                 ),
  19.                 #设置展示平均值
  20.                 markline_opts=options.MarkLineOpts(
  21.                     data=[options.MarkLineItem(type_="average",name="平均值")]
  22.                 ))
  23. line.render()
  24. os.system('open render.html')
复制代码




获取内存数据+画图整体代码:
  1. import timeimport tidevicefrom tidevice._perf import DataTypeimport os#折线图from pyecharts.charts import Line#为图表添加参数from pyecharts import optionst = tidevice.Device()# perf = tidevice.Performance(t,[DataType.CPU, DataType.MEMORY, DataType.NETWORK, DataType.FPS, DataType.PAGE, DataType.SCREENSHOT, DataType.GPU])perf = tidevice.Performance(t,DataType.MEMORY)d = []def callback(_type:tidevice.DataType,value:dict):    print(_type.value,value)    # 处理惩罚数据,拿到内存数值,四舍五入到小数点后一位    mem = round(value['value'],1)    print(mem)    d.append(mem)    # with open('memory.txt','a') as f:    #     f.writelines(value)perf.start('com.xxx.xxx',callback = callback)time.sleep(1800)perf.stop()# print(d)#绘图
  2. x = [i for i in range(len(d))]
  3. y = d
  4. print(x)
  5. print(y)
  6. #创建对象,可以添加一些参数
  7. line = Line(init_opts=options.InitOpts(width='800px',height='600px'))
  8. #添加x轴y轴数据,注意添加y轴数据的时候必须设置series_name参数,表示图例的名称
  9. line.add_xaxis(xaxis_data=x)
  10. line.add_yaxis(series_name='memory', y_axis=y, is_symbol_show=True, label_opts=options.LabelOpts(is_show=False),
  11.                #is_symbol_show=True显示点,label_opts=opts.LabelOpts(is_show=False)不显示值
  12.                #设置展示最大值最小值
  13.                 markpoint_opts=options.MarkPointOpts(
  14.                     data=[
  15.                         options.MarkPointItem(type_="max",name="最大值", symbol="pin", symbol_size=[70,50]),
  16.                         options.MarkPointItem(type_="min", name="最小值",symbol="pin", symbol_size=[70,50], itemstyle_opts={'color':'#3CB371'}),
  17.                     ]
  18.                 ),
  19.                 #设置展示平均值
  20.                 markline_opts=options.MarkLineOpts(
  21.                     data=[options.MarkLineItem(type_="average",name="平均值")]
  22.                 ))
  23. line.render()
  24. os.system('open render.html')
复制代码
后续考虑让脚本更通用,以命令行+参数(只需要更改bundleID)的方式运行。

六、运行wda

目前Mac电脑上,通过appium即可启动运行wda,以是现有的UI自动化不使用tidevice来启动wda;在此介绍Windows电脑上怎样实现iOS自动化,仅供相识。
在Windows电脑上运行iOS自动化,需要用到的环境包括:

  • python
  • tidevice
  • iTools
  • appium v1.20.0以上
  • 已经安装WDA的iOS真机(先用xcode给手机装上webdriveragent,或者把wda打包成ipa装得手机上)
运行WebDriverAgent

目前已经知道的几个题目:


  • 不支持运营企业证书署名的WDA;
  • 数据线大概导致wda毗连中断。作者使用的数据线(推荐): https://item.jd.com/44473991638.html
wdaproxy这个指令会同时调用xctest和relay,另外当wda退出时,会自动重新启动xctest。
  1. # 运行 XCTest 并在PC上监听8200端口转发到手机8100服务
  2. $ tidevice wdaproxy -B com.facebook.wda.WebDriverAgent.Runner --port 8200
复制代码
运行时遇到报错:
tidevice.exceptions.MuxError: [Errno No app matches] com.facebook.wda.WebDriverAgent.Runner
使用tidevice applist命令检察,发现包名是com.facebook.WebDriverAgentRunner.xxxxx.xctrunner,需要记好自己设备上安装的webdriveragentrunner的名称;
可以用tidevice applist检察,然后把命令中com.facebook.wda.WebDriverAgent.Runner替换为自己设备上webdriveragentrunner的名称。
启动后就可以使用Appium或者facebook-wda来运行iOS自动化了。
facebook-wda 示例代码
  1. import wda
  2. c = wda.Client("http://localhost:8200")
  3. print(c.info)
复制代码
Appium需要下面几个配置需要设置一下:


  • automationName:执行引擎,iOS设备需要设置为XCUITest
  • webDriverAgentUrl:iOS运行脚本中,需要配置 webDriverAgentUrl 给 appium driver ,才会不触发 appium 内置的用 xcode 启动 wda 这个流程。否则只要触发这个,appium就会找 xcode 。windows 没有 xcode ,天然跑不下去从而出现报错Error: The usbmuxd socket at '/var/run/usbmuxd' does not exist or is not accessible
  • usePrebuiltWDA:使用已经编译好的WDA。
  • useXctestrunFile:使用Xctestrun文件启动WDA。由于此功能期望您已经构建了WDA项目,因此它既不会检查您是否具有须要的依赖关系来构建,WDA也不会实行构建项目。默认为false。
  • skipLogCapture:跳过开始捕获日志,默认为false。
  1. "webDriverAgentUrl": "http://localhost:8200"
  2. "usePrebuiltWDA": "false",
  3. "useXctestrunFile": "false",
  4. "skipLogCapture": "true",
  5. "automationName": "XCUITest"
复制代码

七、工具对比

  
  tidevice
  libimobiledevice
  简介
  tidevice是阿里开源的iOS自动化测试工具,可以或许提供截图、获取手机信息、ipa包的安装和卸载、根据bundleID启动和停止应用、获取指定应用性能数据、模拟xcode运行xctest等功能。
  libimobiledevice是一个使用原生协议与苹果iOS设备进行通信的库。相当于 Android 的 adb,用于获取iOS设备信息,是 appium 毗连 iOS 设备必需要的依赖库,通过这个库 Mac OS 可轻松得到 iOS 设备信息。
  相同点
  均可提供获取设备信息、卸载安装应用等功能。
  差别点
  安装便捷
  安装较为麻烦,轻易有题目
  可以或许根据bundle ID启动和停止应用
  不能根据bundle ID启动和停止应用
  支持mac/windows/linux体系
  支持mac体系,Linux上可编译安装,不支持Windows体系
  可以或许获取性能数据
  不能直接获取性能数据
  可以启动wda
  不能启动wda
  



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

飞不高

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表