
开篇先说实话Airtest这名字如果你不是做UI自动化的可能有点陌生。但只要干过这行尤其是折腾过Windows桌面端软件回归测试的应该都知道它是网易开源的那套跨平台UI自动化框架能测Android、iOS也能测Windows应用。我最初接触Airtest是为了应付一个PC客户端项目的每日冒烟测试本来计划用pywinauto硬啃结果被窗口句柄飘忽、控件属性缺失折腾到怀疑人生换成Airtest之后整个流程突然就顺了。这篇文章就基于我实际在Windows 10/11上从零安装、配置、编写用例并跑通回归的完整过程把坑和细节一起写出来给准备入坑的人当个地图用。这篇教程适合这几类人看刚接触UI自动化、想在Windows桌面应用上快速落地一套测试方案的测试开发被pywinauto或WinAppDriver搞到心态崩了想换工具的人还有看了一堆文档却不知道怎么设计一套可维护用例的新手。我会从环境准备讲到框架化封装全程带实测案例你可以直接拿去对照操作。1. 为什么要用Airtest做Windows自动化很多人在Windows自动化这条路上第一反应是Selenium——但它只针对Web碰不了桌面软件。桌面端的传统选择是pywinauto、WinAppDriver或者最原始的pyautogui。这些工具不是不能用而是各有各的别扭pywinauto对MFC、WPF、Qt等不同框架的控件识别能力参差不齐碰到自绘控件、WebView嵌套页面基本抓瞎WinAppDriver依赖Appium生态环境配置重稳定性偶尔也闹脾气pyautogui就是纯粹按坐标瞎点换个分辨率、改个窗口大小脚本直接报废。Airtest走的路线不太一样核心思路是图像识别 UI控件树双引擎。它能直接截取屏幕画面通过图像特征匹配定位元素这在处理自绘控件、游戏界面、视频渲染区域时特别顶用。同时针对Windows标准控件它也能像Appium那样读取UI树结构拿到控件的属性来做精准操作。两套定位机制互为兜底比单纯依赖某一种方式稳得多。另外有个很实际的原因AirtestIDE是个开箱即用的图形化工具自带录制回放、元素拾取、脚本编辑、报告生成一整套能力。你不写一行代码先录一段操作再调整逻辑就能跑出一条可用的用例对刚入门的同学非常友好。而当你需要把它集成进CI/CD流水线时它又能抽出来以纯Python库的形式运行灵活度不输其他框架。2. Windows环境准备与Airtest安装全流程2.1 环境要求先确认机器够不够格Airtest对Windows系统的门槛其实很低我实测过Win10 21H2和Win11 23H2都能正常工作。需要注意的点主要有以下几个操作系统Windows 7 SP1及以上的理论上都行但强烈建议Win10 64位以上。Win7的兼容性有历史坑比如某些DLL缺失新版本Airtest已经不保证支持了。Python环境如果走纯库路线Python 3.7到3.11实测都能装3.12有些依赖可能还没跟上建议用3.9或3.10最稳。屏幕分辨率建议至少1920x1080分辨率太低时图像识别容易误匹配尤其是小图标密集的界面。硬件CPU和内存没什么硬性要求但图像识别是CPU密集操作老双核机器跑大图匹配会明显卡顿实测i5-8250U跑一个用例大约30秒性能好的机器10秒内能完成。2.2 安装AirtestIDE最省事的官方方案如果你只是想快速上手先别折腾代码环境直接装AirtestIDE就行。它是网易官方提供的集成开发环境把Airtest核心库、Poco库、报告生成工具都打包好了一个安装包解决所有问题。去GitHub的Airtest项目Release页面或者NetEase官网找Windows版本下载一个类似AirtestIDE_xxxx_x64.zip的压缩包解压即用不用执行安装程序。这一点跟绿色软件似的解压之后双击AirtestIDE.exe就能启动。解压路径有讲究最好不要放在C盘Program Files这种权限受限的目录也不要有中文字符和空格。我一开始放在D:\Program Files (x86)\路径下结果启动后部分功能异常后来换到D:\AirtestIDE\就正常了怀疑跟启动时写入配置文件的权限有关。启动之后IDE界面主要分三大块左侧是设备连接面板和设备窗口中间是脚本编辑区右侧是运行选项和日志控制台。初次进入会让你选择脚本语言模板直接选Airtest模板就行。2.3 用pip安装Airtest库给命令行用户的路子对于要跑自动化回归、接入CI系统的场景光有IDE不够还得装Python库。安装命令很简单pip install airtest但这里有个容易踩的坑Airtest依赖的opencv、numpy、pandas等包版本和最新版不总是兼容。我遇到过pip直接把numpy升到2.x结果opencv调用报错的情况。稳妥做法是优先装pocoui和airtest的固定版本组合pip install airtest1.3.3 pip install pocoui1.0.87如果你机器上同时有多个Python版本务必先切换到目标虚拟环境再装不然会出现库找不到、模块冲突等莫名其妙的问题。推荐用Anaconda或者python自带的venv隔离环境这个习惯越早养成越省心。装完可以检查一下pip show airtest能看到版本信息就算装成功了。2.4 配置ADB与Windows驱动Airtest连接Android设备时需要ADB连接Windows设备时其实不需要额外驱动它是直接通过桌面截屏和模拟输入来实现控制的。但这个环节很多人会卡一下连不上设备、黑屏、无法点击。这通常是因为没有开启ADB服务或者Windows图形界面权限的问题。在IDE里连接Windows设备时它会在后台调用一个名为airtest.core.win.win的Windows窗口控制器通过句柄和坐标完成操作。操作前建议关闭其他可能干扰的弹窗程序比如各种安全软件的拦截确认框实测某些安全工具会拦截模拟输入导致点击没反应。我当时的组合是AirtestIDE解压版 Python 3.9虚拟环境 airtest库1.3.3版本搭配Win10专业版运行两个月没有出现过连接层崩溃的问题。后面在Win11上试过同样组合也正常。如果新版本有兼容性问题这个组合可以说是最朴素的保底方案。3. Windows自动化核心概念与实测准备3.1 连接Windows设备的几种方式在AirtestIDE里操作路径是右侧设备面板 - 点击连接到Windows。这一步会弹出一个窗口直接展示当前桌面的实时画面相当于把整个桌面当成被测对象。IDE里的连接和后续的脚本操作本质上是不断截取桌面图像然后跟你的脚本所引用的图像做匹配。批处理或纯代码情况下写法是这样from airtest.core.api import * auto_setup(__file__, logdirTrue) dev connect_device(Windows:///) touch((100, 200))注意connect_device参数里Windows:///是固定的表示连接当前桌面。如果你需要操作的窗口在远程主机上Airtest也支持Windows:///远程IP的形式连接前提是同一局域网且开启了相关服务。3.2 图像识别原理Airtest是怎么“看见”的图像定位是Airtest的核心能力。它内置了一个基于OpenCV的模板匹配引擎原理是拿你截图的小图比如按钮区域作为模板在当前大的屏幕截图上做滑动窗口匹配计算相似度相似度超过阈值就认为找到了目标。这里有个关键参数叫threshold默认是0.7也就是70%相似度即判定命中。这个值在不同场景下需要调整高对比度、界面稳定的按钮比如登录按钮0.7就能稳定命中。底色相近的输入框、列表项建议调到0.85以上防止误匹配。动态渲染的图标比如某个加载动画中的按钮建议降到0.5以下但低阈值也有风险可能匹配到错误的区域。代码里可以这么指定touch(Template(rD:\test\login_btn.png, threshold0.8))图像来源可以是任何截图工具截好的图但更推荐在AirtestIDE里用截取屏幕功能直接截取这样它会把截图的区域信息和期望分辨率一起记录下来生成的图片以.png格式存在脚本目录下可读性好也方便后续维护。3.3 坐标体系与窗口定位注意Airtest在Windows上的坐标基准是整个屏幕不是某个窗口内部。这就产生了一个常见问题当你把窗口从屏幕左上角拖到右下角时脚本里写死的坐标全部失准。解决办法是操作前先获取目标窗口的位置信息然后动态计算坐标偏移。用Poco识别窗口控件时拿到的坐标是相对窗口的转换为屏幕坐标需要再加窗口左上角坐标。这块在4.2节里我会给出具体代码。如果你只是做快速冒烟不追求跨窗口场景的鲁棒性直接写死坐标也没问题——前提是你知道自己放弃的是什么。4. 完整用例自动化一个Windows应用的登录与数据校验流程4.1 场景选择与测试准备我拿一个自己开发的小工具——一个本地记事本风格的极简CRM客户端来演示Airtest的完整自动化流程。这类原生Win32/WPF窗口程序控件属性比较规范Airtest识别很流畅适合拿来当教学模板。测试目标验证用户能通过正确的账号密码登录登录成功后能进入主页面并看到待办列表数据。测试步骤设计启动目标应用。在用户名输入框输入用户名。在密码框输入密码。点击登录按钮。等待主界面加载完成。校验主界面上的欢迎文本是否为预期结果。输出测试报告。4.2 脚本编写过程实录先放完整脚本然后重点解析每一段的含义。# -*- encodingutf8 -*- __author__ Tester from airtest.core.api import * from airtest.core.win import Windows from poco.drivers.windows import WindowsPoco auto_setup(__file__, logdirTrue, devices[Windows:///]) # 1. 启动目标应用 import subprocess subprocess.Popen(rD:\apps\CrmDemo\CrmDemo.exe) # 等待窗口出现 sleep(2.0) # 2. 用Poco定位控件并输入内容 poco WindowsPoco(addr(localhost, 50001)) username_input poco(Window).child(usernameTextBox) username_input.set_text(admin) password_input poco(Window).child(passwordTextBox) password_input.set_text(123456) # 3. 点击登录按钮 login_btn poco(Window).child(loginButton) login_btn.click() # 4. 等待主界面渲染完成 sleep(3.0) # 5. 用图像识别校验欢迎文本 welcome Template(rD:\test\welcome_label.png, threshold0.8) assert_exists(welcome, 主界面欢迎文本存在) # 6. 截图留存 snapshot(filenamelogin_success.png, quality80, max_size1280) print(登录用例通过)这段脚本逻辑很直观。第1步用subprocess启动应用这比直接用Airtest的start_app指令更稳定。Airtest的start_app主要针对Android在Windows下偶尔遇到进程无法拉起的问题。第2步的Poco定位是Windows自动化里最值得学习的地方。Poco在这里不是走图像识别而是通过Windows UI AutomationUIA机制解析当前界面的控件树然后用属性路径来寻找元素。所以它找元素靠的是控件的自动化ID或者Name属性响应速度快也不会受分辨率变化影响。有个坑要注意WindowsPoco示例里我写了addr(localhost, 50001)这个其实是AirtestIDE启动Poco服务时的端口。当你用纯Python环境时这个参数通常不需要指定直接用WindowsPoco()就好。指定端口反而会报连接失败。当时我第一次写代码时直接照搬了IDE自动生成的代码在命令行跑直接崩溃折腾了半天才发现是端口的问题。第5步的assert_exists是断言API如果图像匹配失败它会直接抛异常用例就会标记为失败。这种方式适合做结果校验比无脑sleep更靠谱。4.3 运行调试与结果分析在IDE里运行这段脚本点运行按钮后会看到实时画面、日志输出和报告预览。跑通后建议用命令行方式跑一次验证脱离IDE后脚本是否依然可靠python test_login.py运行结束后Airtest会在当前脚本目录下生成一个log.html报告文件里面包含每一步的截图、操作结果、耗时等。这个报告拿来做测试存档或者给项目组汇报都是现成的材料。实测跑出来的结果截图会显示点击登录按钮那一帧的屏幕截图、执行完登录后主界面的截图、以及两个断言的通过状态。整个用例时间大约12秒其中图像识别占了3到4秒Poco控件定位和操作占1秒左右其余主要是等待时间和启动时间。5. 常见问题与排查技巧5.1 Windows连接失败或黑屏问题现象点击连接Windows设备提示连接成功但显示黑屏或者完全连不上。排查路径确认脚本或IDE里用的设备连接参数是Windows:///不是Android:///这也是新手最容易犯的低级错误。检查AirtestIDE版本旧版本对Win11兼容性差升级到最新版能解决大半问题。关闭任何会全屏覆盖的软件比如远程控制工具、录屏软件、动态壁纸工具。这些软件会抢GPU渲染或鼠标键盘事件Airtest拿到的截屏可能是空白或卡顿的。检查屏幕分辨率设置强烈建议缩放比例设为100%。Windows的显示缩放在125%、150%时Airtest的坐标映射会偏移点击位置对不上。解决办法在Windows显示设置里把缩放改成100%重新连接设备就好了。5.2 图像识别匹配失败问题现象assert_exists明明指向一个屏幕上肉眼可见的按钮却报找不到目标。核心原因一般有三个截图模板的分辨率跟实际屏幕显示不一致。比如模板是从1920x1080下截的图实际测试机是2560x1440匹配算法用不同尺度匹配会找不到合适的比例导致相似度大幅下降。解决办法是统一测试机分辨率或者把模板截图重新截取一次。按钮有动态状态变化。比如登录按钮在鼠标悬停时颜色变了而你截的模板是普通态匹配就失败了。这种时候要么截一个最通用状态的图要么调低阈值到0.6左右。界面有透明或半透明遮罩。某些弹层弹出来时底下元素被半透明蒙层覆盖图像颜色发生了变化匹配自然失败。先处理弹层再继续操作。5.3 文本输入异常问题现象set_text执行后目标控件没有写入内容或输入的是乱码。排查方案确认目标控件是否能正常获取焦点可以先点击一下再set_text。输入中文失败是常见问题Airtest的文本输入接口在Windows上对中文字符支持不太稳定。绕行方案是用系统剪贴板粘贴import pyperclip pyperclip.copy(用户名) keyevent({CTRL}v)这段代码先把文本复制到剪贴板再模拟CtrlV粘贴实测中文输入成功率100%。某些游戏或特殊渲染框架如CEF内嵌页面不接受模拟按键需要用Poco控件的set_text内部机制这依赖被测应用是否实现了UIA的ValuePattern如果实现不到位只能靠剪贴板方案或者逐字符输入。5.4 日志和报告不生成问题现象脚本能跑通但log.html没生成或者报告里没有截图。原因通常是auto_setup里的logdir参数没生效。确保写法是auto_setup(__file__, logdirTrue)注意logdirTrue才会自动创建timestamp目录如果改成logdirNone或者不写log会跑到默认临时目录里权限不够时就直接放弃了。另外运行完脚本后报告不会自动打开浏览器需要手动打开log目录下的log.html。这里还有个容易忽略的点报告里的截图默认保存在log目录下的log_screen文件夹里如果你把脚本目录配置了自动清理或杀毒软件扫描白名单之外的路径文件可能被误删。我当时就是开发环境根目录下日志图片时不时消失排查了一圈才发现是安全软件把log_screen下的png当临时文件清掉了。6. 测试用例设计思路与框架化建议6.1 用例的粒度怎么定接触Airtest一段时间后很多人会把它当成单纯的录制回放工具来用。这没有错但真要落地到项目里用例的粒度直接决定维护成本。我建议的粒度标准一条用例只验证一个核心业务场景但允许包含多个操作步骤。比如上面登录用例业务流程是启动应用、输入账号、输入密码、点击登录、校验结果这是一个完整的场景。不要把它拆成五条独立用例否则只会徒增脚本量运行时间被不断拉长而且前后依赖关系会变成噩梦。反过来如果一条用例里塞了太多分支比如登录、新建、删除、导出全塞在一起一旦中间某一步失败后面全挂定位问题要花半小时这种用例也是垃圾设计。正确的做法是每个测试目标独立成脚本公共步骤抽成模块例如登录操作抽成一个独立函数不同用例调用它。6.2 从脚本到框架pytest Airtest当用例数量超过20条后裸脚本就无法支撑了至少要引入pytest组织用例加上allure或原生报告生成好看的结果。一个基本的pytestAirtest工程目录可以这么组织test_project/ ├── conftest.py # 定义fixture负责启动应用/关闭应用 ├── pages/ │ ├── login_page.py # 封装登录页的操作 │ └── main_page.py # 封装主页面操作 ├── tests/ │ ├── test_login.py │ ├── test_create_record.py │ └── test_export.py └── airtest_scripts/ ├── login.py # airtest离线脚本 └── common_util.py每条测试用例里做三件事setup启动应用和连接设备、执行操作、断言结果。Airtest断言API很好用assert_exists和assert_not_exists直接对应测试预期。def test_login_success(): login_page.init() login_page.login(admin, 123456) assert_exists(main_page_welcome, 主界面加载成功) snapshot()结合pytest的fixture功能把启动目标应用这个重复操作提取到conftest里import pytest from airtest.core.api import * from airtest.core.win import Windows pytest.fixture(scopemodule) def connect_windows(): auto_setup(__file__, logdirTrue) start_app_windows() yield stop_app_windows()注意scopemodule表示一个测试文件内共用同一个连接会话避免每个用例都重新启动应用大幅提升执行效率。这套框架跑起来后配合Jenkins或GitLab CI就能实现每天晚上定时跑回归早上起来直接看报告。我实际用下来一个包含50条用例的Windows客户端回归集全量跑完大约30到40分钟单用例失败率稳定在5%以下。相比之前纯手工回归两台机器打一上午效率提升非常明显。一些经验性总结最后分享几个只有真正跑过一段时间才会意识到的细节。第一Airtest的稳定性高度依赖测试环境的“干净度”。被测机器最好是专用测试机不要一边跑着Airtest一边开着微信、钉钉、QQ。这些应用有独立的系统级弹窗偶尔还抢焦点一弹窗你的脚本点击就全跑偏了。我在测试机上专门建了一个最小化系统配置只装被测应用和必要依赖之后用例失败率直接下降了一半。第二别迷信图像识别。能走Poco控件定位的时候优先用PocoPoco识别不了的时候再退而求其次用图像识别。图像识别在低分辨率、高缩放、动态界面上非常脆弱是脚本不稳定性的头号来源。可以把Poco理解为控制流把图像识别理解为兜底断言的补充手段。第三报告和日志要早配。不管你是一个人做测试还是团队协作运行完的日志就是排查问题的主要线索。Airtest自带的报告结构对技术同学来说够用了截图会标注每步操作的具体位置报错时翻日志基本能定位到具体元素。第四适当关注内存占用。使用Periodic测试时长时间运行的Airtest进程内存占用量会缓慢上升。如果脚本是循环执行建议每隔一段时间重启进程。我自己在跑一个整夜回归任务时跑到凌晨后系统资源占用飙高重启了脚本进程才恢复稳定。第五Airtest的社区资料比较零散官方文档优先看英文版。中文社区里不少内容停留在老版本照着做会遇到各种莫名其妙的报错。我踩过的坑中大约有两成是版本不兼容导致的所以再次强调环境版本一定要先锁定再动手写代码。这篇教程从安装写到框架化基本把Windows端Airtest从零到能落地使用的流程捋了一遍。如果你在实操中遇到这里没覆盖到的问题欢迎根据我提到的排查思路倒查——大部分问题都逃不出环境、版本、图像匹配、焦点抢占这几个圈。