资讯动态

用Airtest跑通第一个iOS脚本:真机连接与断连排查实战

发布时间:2026/10/13 14:22:10 来源:尧图企业网站定制
做iOS自动化测试这几年见过太多人卡在同一个地方脚本还没写设备先连不上。安卓那边插上USB、开个USB调试几分钟就能跑起来iOS这边要Xcode、要证书、要XCTest那套体系链路一长新手很容易一上来就心态爆炸。这篇继续Airtest实战系列前面已经把工具安装和安卓端脚本基础讲完了这次专门讲怎么用Airtest编写并跑通第一个iOS设备脚本从真机连接到脚本骨架再到我踩过的断连问题一次说透。适合已经装好Airtest、看过安卓脚本样例但第一次面对iOS真机的同学。1. 为什么iOS脚本总先死在“连接”这一步先说结论iOS的自动化通道本质上是“曲线救国”。安卓有官方提供的ADB通道开发者模式一开电脑就能对设备发指令iOS这边没有对UI自动化完全开放的通用通道。Airtest要控制iOS真机实际是把一个叫WDA的测试Runner跑到设备上通过它暴露HTTP接口脚本再通过这个接口去发点击、滑动、截图这些指令。所以你会看到Airtest连安卓时一个connect_device就完事连iOS时却总冒出证书、信任、端口之类的问题。因为你的电脑不是直接操作设备而是先要在设备上“安装”一个自动化代理再和它对话。这一步没理清后面所有报错都会显得毫无规律。我把安卓和iOS在Airtest里的连接差异整理成一张表方便你对比着看。对比项安卓iOS控制通道ADB直连WDA XCTest设备授权USB调试开关开发者模式 信任证书连接方式USB即可USB或网络代理端口控件能力控件树较完整控件树依赖额外服务最常见卡点驱动缺失证书失效 / WDA未信任1.1 iOS自动化链路多出来的一层桥WDA这个东西说起来不算复杂。它本质上是跑到iOS设备里的一个测试进程系统把U它当成一个日常的UI测试Runner来调度。WDA启动之后会在设备上开一个HTTP服务Airtest脚本发过去的点击、滑动、截图请求由它翻译成XCTest能理解的操作再作用到屏幕上。也就是说脚本与设备之间永远夹着这层代理。它在链路就通它不在脚本什么都做不了。理解这层关系很重要。后面遇到“连接不上”“中途断开”这类问题第一反应不该是重写脚本而是先问一句WDA还活着吗HTTP服务还回话吗端口转发还在吗我见过不少同事报错之后一遍一遍调脚本结果问题出在设备上的代理进程早就被系统回收了纯做无用功。1.2 开始写脚本前要满足的真机条件在打开Airtest之前请先把下面的条件一项一项过一遍缺一项后面都会以各种诡异的方式报错。一台Mac电脑装着XcodeWDA基本绕不开编译、签名、安装这几步Windows上没法直接跑这套流程。一台iOS真机系统设置里的开发者模式必须先打开这里最容易被忽略iOS 16以后默认是关闭的不手动开连多久都连不上。一个可用开发者身份个人免费证书也能跑但有个坑后面会详细说总之先准备一个能签名的身份。一根靠谱的数据线尽量用原装或带数据传输能力的线很多“识别不了设备”其实只是线只能充电。设备首次连接时需要点击“信任这台电脑”弹窗这个弹窗不点后续所有USB通讯都会被系统拦掉。第一次连的时候最容易被忽略的就是“开发者模式”这个开关。很多人把证书、WDA、代理全弄好了连Airtest还是黑屏画面最后发现只是手机上的开发者模式没开。我见过至少三次这样的现场每次排查都要花半小时。2. 一套能跑通的真机环境安装、设备识别与WDA环境准备这种事第一次做最烦因为每一步都可能失败。但只要你把“截图能出来”作为链路打通的标志判断起来就简单很多。Airtest脚本再复杂最终都依赖这条链路能不能用。2.1 安装Airtest并让设备出现在连接列表里Airtest推荐用IDE版本不只是因为它可视化更因为IDE把WDA的安装引导和设备列表做成了界面操作对新手友好很多。纯命令行安装虽然也能跑但WDA的准备环节很容易和电脑本身的代理端口、Xcode版本纠缠在一起踩坑成本高。先用IDE把流程跑通后面熟悉了再切命令行会舒服很多。安装完成之后打开IDE的设备连接面板选择iOS设备。如果看到设备出现在列表里先别急着写脚本用下面这段代码做一次连接验证from airtool.core.api import connect_device connect_device(iOS:///)不同版本的Airtest对iOS连接串的写法略有不同。新版一般可以直接写iOS:///让它自动发现USB设备老版本可能会需要先做端口转发再写成iOS:///127.0.0.1:8100。你如果发现一行connect_device跑不通别硬刚去确认一下手头Airtest版本对应的连接方式。这类坑通常不是语法问题而是版本差异。2.2 WDA的首次安装与信任流程WDA的首次安装可以直接在Airtest IDE里通过引导完成。点击连接iOS设备后IDE一般会提示需要安装WDA按提示走。如果你想自己用Xcode装也完全可以打开WDA工程选择Runner这个target把签名身份选好让Xcode把它跑到设备上。第一次安装成功后必须去手机的“设置-通用-设备管理”里信任对应的开发者App否则WDA根本启动不了。这一步的报错通常长这样脚本一启动就退出日志里出现“unable to launch”之类的提示。如果你看到这类错误不要急着去改脚本先检查设备管理里有没有完成信任。这个问题在免费开发者身份上尤为明显因为免费证书有效期只有7天过期之后WDA就会启动失败表现出来的就是一切正常但就是连不上。2.3 用一次截屏验证链路已通环境到底装没装好不用看一堆日志直接截一张图最直观。验证脚本很短from airtest.core.api import * connect_device(iOS:///) snapshot(filenamefirst_check.png)跑完之后去脚本目录看看first_check.png有没有生成。如果生成的是正常桌面画面说明电脑到WDA再到屏幕的整条链路已经通了。这时候你才算真正拥有了编写iOS脚本的资格。很多第一次接触iOS自动化的人会跳过这一步直接写业务脚本结果一个简单的touch失败分不清是环境问题还是脚本问题。还有个小提醒首次验证的时候手机尽量保持解锁状态屏幕常亮选项也顺手开一下。自动化脚本运行期间一旦锁屏很多操作会直接失效但报错信息非常不直观。3. 第一个iOS脚本截图匹配的启动、滑动与断言环境通了接下来才是真正写脚本。我强烈建议你第一个iOS脚本不要写业务细节只做一个30秒能跑完的冒烟用例启动App、等待首页、截图、滑动手势、断言一个关键元素。这套动作虽简单却能覆盖Airtest在iOS上80%的基础能力后续所有业务脚本基本就是这个骨架的扩展。3.1 脚本目标与设计思路这个脚本的任务是启动被测App确认首页加载出来然后模拟一次滑动再点击一个目标位置最后截图并断言操作结果。被测的App你随意选最好是自己熟悉页面的那种哪怕只是一个自写Demo都行。设计思路是这样的先用截图匹配的方式做操作定位因为它是Airtest在iOS上最稳定的定位手段。控件树能不能拿到取决于App本身和Poco的部署情况但屏幕上的画面一定存在只要画面存在截图匹配就一定可用。把这个最稳定的姿态作为第一个脚本的基础能最大程度减少变量。3.2 完整脚本骨架与API解释直接给一份能跑的骨架你把自己App的bundle id和两张截图模板替换掉就行。模板图片怎么来在Airtest IDE里连接设备后可以直接框选屏幕上的目标区域保存成模板文件放到脚本目录里。from airtest.core.api import * def main(): connect_device(iOS:///) # 启动被测App参数是bundle id可在Airtest IDE设备面板查询 start_app(your.app.bundle.id) sleep(2) # 断言首页出现tpl_home.png 是首页关键区域截图 assert_exists(Template(rtpl_home.png, threshold0.8), 首页加载成功) # 模拟从右往左的滑动坐标按当前设备逻辑分辨率简单示意 swipe((400, 700), (80, 700), duration0.5, steps10) sleep(1) # 滑完后截图便于后面看效果 snapshot(filenameafter_swipe.png) # 点击目标按钮tpl_button.png 是需要点击的位置截图 touch(Template(rtpl_button.png, threshold0.8), 点击目标按钮) sleep(2) # 断言点击后的结果页出现 assert_exists(Template(rtpl_result.png, threshold0.8), 操作成功) print(first ios script done) if __name__ __main__: main()几个关键的API我展开说说。start_app接收的是bundle id不是App名称Airtest IDE的设备面板里能直接查到已安装应用对应的bundle id。Template是截图匹配的核心图片路径一般写相对路径模板文件放在脚本目录下最省事。threshold是相似度阈值0.8是个比较常用的起点太低容易误匹配太高容易匹配不上这个参数值得在你自己的App上多调几次。assert_exists在断言失败时Airtest会自动保存一张现场截图到日志目录这对后面排查问题非常有用。3.3 为什么第一个脚本不急着上Poco很多从安卓转到iOS的人会习惯性地打开Poco取控件树然后发现iOS这边Poco的接入成本高了一大截。原因在于iOS端Poco同样依赖WDA提供页面快照但不少第三方App尤其是游戏和混合应用页面树并不完整。你要先花精力把Poco本身调通又得处理WebView、原生控件的差异等于在业务脚本之外额外多扛一套复杂度。第一个脚本的核心目标是建立最稳定的闭环所以先用截图匹配。这套机制不依赖控件树只要眼睛能看到界面它就能工作。等你把基础链路跑稳了再评估当前项目要不要上Poco那时候你对设备和脚本的掌控力已经不一样了不会因为Poco不工作而怀疑整个方案。4. 跑通后的头号大坑连接中断与WDA失联排查脚本跑通不是终点能稳定跑完一批才是。我在iOS脚本上遇到过最典型的问题就是脚本跑得好好的突然报连接丢失。表面看是网络或USB问题实际上背后通常是一连串环境状态的叠加。这里有完整的排查链路我把它梳理出来。4.1 现场现象与日志特征最常见的报错有两类。一类是connection lost另一类是socket closed或Connection aborted。出现这类报错时脚本执行到一半就停了后续的断言和截图全部不会执行。如果你用的是Airtest IDE界面上会直接断开设备连接命令行跑的话日志最后几行会出现明显的断开关键字。这里有个容易忽略的点跑脚本之前明明连接是好的为什么跑到一半会断开大概率不是初始连接的问题而是运行过程中某件环境事件破坏了链路比如电脑休眠、手机锁屏、Mac切换网络、WDA进程被系统回收。先别急着重写脚本而是往下走排查流程。4.2 从端口到证书的排查链路我个人的排查顺序是固定的从最底层往上查基本五分钟内能定位。第一步看日志最后几行。Airtest的日志会记录连接状态和设备反馈如果日志里出现了HTTP层面的异常比如status code 500说明设备端WDA可能已经不在正常工作状态。如果日志只停留在断连前的一条指令那更偏向于物理链路问题。第二步检查端口转发和WDA状态。手动验证时可以先停掉Airtest的连接单独做一次端口转发然后请求WDA的状态页。可以用下面这两条命令iproxy 8100 8100 -u 你的设备UDID curl http://127.0.0.1:8100/status如果status返回了正常的JSON信息说明WDA活着问题更多在脚本与设备的会话上如果请求直接失败或返回一堆错误码说明设备端的自动化代理已经没了需要重新拉起WDA。注意端口不能和Airtest IDE同时占用否则会互相冲突。第三步检查证书有效期。免费开发者身份签出的WDA7天就过期。过期后最典型的表征是Xcode能打开、连接能建立但一切指令都发不出去日志里报启动失败。这时候最快的处理方式是用Xcode重新把WDA跑到设备上并去设备管理里重新信任一次。下面这张表汇总了我遇到过的几种典型报错方便你对照。报错现象最大可能原因第一动作无法连接设备或找不到设备USB未信任 / 开发者模式未开看手机屏幕弹窗确认开发者模式脚本启动后立刻断开WDA未信任 / 证书失效去设备管理信任或重签WDA跑几个用例后socket closed长连接被回收 / 电脑休眠关闭休眠保持屏幕常亮截图一直是黑屏设备锁屏 / 屏幕常亮被关解锁设备重新点亮屏幕4.3 让长跑脚本更稳的三个预防动作排查只是事后补救真正要做的还是预防。我自己在长期跑iOS脚本后总结出三条纪律。第一电脑休眠必须关掉。跑脚本期间Mac休眠USB链路和网络通道都会中断恢复后WDA不会自动重连这是断连的第一大诱因。第二手机屏幕常亮开着并保持充电状态。iOS设备息屏后后台进程很容易被系统调度回收WDA一旦被回收等再亮屏时链路已经断了。第三长时间回归批次里不要一直复用同一个WDA会话跑完一批用例后主动断开重连一次。长连接挂久了iOS端容易出各种不可预期的状态定期重置反而更稳。5. 从“能跑”变成“好用”报告、多机型适配与CI接入第一个脚本能稳定跑通之后你会很快遇到新的需求这个脚本怎么给别人看换个机型还能不能跑怎么在持续集成里每天自动执行这些问题都能解决但需要注意的细节不少。5.1 出问题后怎么从报告里快速定位Airtest自带一套报告机制每个步骤会关联截图和日志。在IDE里运行完脚本点查看报告可以看到每一步的操作截图、断言结果、失败现场。命令行跑脚本时也可以自己生成报告airtest run untitled.air --device iOS:/// --log log/ airtest report untitled.air --log_root log/ --out report.html这套报告最实用的地方在于断言失败时Airtest会把失败时刻的屏幕截图直接留在报告里。你不需要回看一整段录屏只需要看断言对应的那一步就能判断是页面没加载出来还是相似度阈值不够导致误判。我在定位问题时85%的情况靠报告加日志就能解决连真机都不用重新拿起来。5.2 多机型下截图匹配的适配习惯截图匹配在单一机型上很稳定一旦换成不同分辨率的设备就可能出现匹配不到或者误匹配的情况。我的习惯是把模板图片尽量从高分辨率设备上截取保证画面细节更充分。对于不同屏幕尺寸的机型单纯调大调小阈值不一定有效更好的做法是给主要机型分别维护一套模板或者让脚本读取设备分辨率按比例换算关键坐标再结合截图做二次确认。还有一个细节模板截图的区域不要太大尽量选特征明显、文案固定的区域。比如App底部的一个固定按钮、导航栏的关键标题这些不容易受页面滚动影响。如果你截了整张屏幕当模板一点细微差异就可能匹配失败调试成本会高很多。5.3 接入持续集成前必须想清楚的三件事如果你准备把这套脚本交给持续集成先想清楚三件事。第一证书管理。免费身份的证书7天过期在本地你还能手动重签到了CI机器上半夜证书失效会让自动化任务看起来像产品Bug排查起来非常痛苦。有条件的话至少弄个不限制有效期的开发者身份或者写好证书刷新脚本。第二设备队列。并行跑多台iOS设备时每个设备上的WDA实例要分开管理端口不能共享。一台设备对应一组独立转发和连接配置否则会出现两台设备互相抢占的诡异问题。第三失败重跑机制。iOS环境稳定性再好也会有系统弹窗、网络抖动这种偶发干扰。给CI脚本加一层失败重跑能明显拉高整体通过率也比每次失败都人工介入要省心得多。这一篇只做到“第一个脚本能稳定跑”这步。说实话iOS自动化的水很深很多问题都是环境层面的脚本本身反而简单。我自己的经验是不要一上来就铺很多用例先用一个冒烟脚本把设备、WDA、截图、断言、报告整条链路跑三遍确认每一次运行都稳定再开始扩业务用例。最后再强调一次跑iOS脚本期间电脑别休眠手机屏幕常亮开着不插电的话很容易中途锁屏别问我怎么知道的。就先到这儿后面有空继续写iOS里的Poco和复杂手势。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑