ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Appium移动端自动化测试入门:从环境搭建到元素定位的完整指南

Appium移动端自动化测试入门:从环境搭建到元素定位的完整指南 先说明我写这篇东西的动机这几年身边越来越多人想学移动端自动化一搜“Appium”相关的资料不是培训机构几年前的视频就是一堆只贴报错没人回帖的求助帖。真正能把环境装好、第一个脚本跑通、顺带把原理讲明白的教程其实很少。我自己从踩坑到给团队搭框架前前后后折腾了不少时间把入门路上那些关键节点一次性说清楚。这篇文章适合两类人完全没接触过自动化测试、想系统入门的新人以及已经写过一些脚本但对环境配置、元素定位和稳定性排查还比较模糊的同学。我会从原理讲到实操再给你一份可以直接照着做的避坑清单。1. 入门之前先搞懂它在解决什么问题1.1 Appium不是“一个工具”而是一套转发协议很多人第一次用Appium时容易懵觉得它既像服务又像客户端一会儿要装Node.js一会儿又要装Appium Server还没开始写代码就先被环境劝退了一半。把它的运行架构搞清楚后面的路会顺很多。Appium本质上是前后端分离的架构你写的测试代码Java、Python、JS都行通过HTTP请求把“打开这个App、点那个按钮”之类的命令发给Appium ServerAppium Server再把这个命令翻译成手机系统能听懂的语言Android平台默认走UiAutomator2驱动iOS平台走XCUITest驱动最后由这些驱动去操作真实设备上的元素。可以把它比作餐厅点菜测试代码是点菜的人Appium Server是传菜的服务员UiAutomator2和XCUITest是后厨手机就是灶台。点菜的人只需要按菜单点不用关心后厨怎么切菜、用什么锅后厨换了菜系菜单还是同一份。这也是Appium最大的卖点——跨平台统一接口。你写一套测试逻辑换个手机平台往往只需要改配置参数不需要把用例逻辑推翻重写。这个设计思路继承自Web自动化里的WebDriver协议。浏览器自动化用WebDriver来标准化“在页面上找元素、点击、输入”这些操作Appium把同一套协议扩展到了移动端所以用过Selenium的人上手Appium会非常快定位、等待、断言这些概念几乎是顺滑迁移的。1.2 同类的移动端测试框架不少为什么先学它国内测试圈子能听到不少同类工具比如uiautomator2、Airtest、Macaca。每个都有存在的理由但作为入门第一套戏我还是推荐Appium理由有三点跨端能力、语言生态、社区规模。uiautomator2是阿里的开源项目脚本轻量、上手快但它是Android专用而且主要绑定Python想同时覆盖iOS就得另起炉灶。Airtest非常友好图像识别的方式对游戏和零基础选手很友好但一旦遇到复杂的原生控件结构、需要精确断言还是不如基于控件树的定位可靠。Macaca早年很火不过社区活跃度和资料丰富度已经明显下滑。Appium的优势在于它把“用什么语言不重要”这件事做到了极致。团队里有人会Python有人写Java还有人用JS大家都能在同一套框架下协作再加上资料多、踩坑帖子多遇到问题几乎都能搜到答案。它确实“重”一些性能方面也不如轻量级方案高但对你理解移动自动化底层的这套逻辑帮助最大。入门阶段选一个生态最稳的框架去啃远比一开始就在各种工具间横向对比更重要。2. 环境搭建要点这一步决定你能否跑通第一个脚本2.1 前置软件清单与环境变量配置环境搭建是Appium入门劝退率最高的环节问题大多不是某个软件装不上而是版本之间互相不认识。下面是我在实际环境里验证过的一套组合你照着准备就行。首先确认四样东西JDK8或11都行Appium 2.x对此没有强绑定但Android工具链对JDK版本有要求建议直接上11Android SDK包含adb、platform-tools、emulator等Node.jsAppium Server的运行环境建议装14以上的LTS版本Appium Inspector独立出来的图形化元素定位工具JDK安装完成后命令行里输入java -version能看到版本号就算成功。Android SDK的坑稍微多一点装完之后要配置两个环境变量ANDROID_HOME指向SDK的根目录比如我这边是D:\Android\Sdk然后把platform-tools和emulator这两个子目录加进PATH。配置完在终端输入adb devices能看到设备列表就说明环境变量生效了。我遇到过不少同学检查半天才发现是环境变量没有生效问就是“明明配了”但命令窗口是配之前打开的重开一个就正常了。第一条避坑笔记先记下改完环境变量一定要开一个全新的终端窗口别在旧窗口里测试它不会自动重新加载。2.2 Appium 2.x安装与驱动的正确姿势以前用Appium 1.x的时代装完Appium Desktop后图形界面里自带Server和Inspector一个安装包搞定。现在Appium 2.x把Server和Inspector拆开了Server用命令行跑Inspector是独立的桌面程序很多人找不到老的“Appium.app”入口就在这里迷路。安装Server和驱动也比较直接npm install -g appium appium driver install uiautomator2第一条命令装的是Appium Server本体第二条给Android装上UiAutomator2驱动。装完之后用appium -v看版本用appium driver list --installed确认驱动是不是装上了。运行的时候不用打开任何图形界面直接在终端启动appium -p 4723 -a 127.0.0.1-p指定端口默认是4723-a指定监听地址本地调试就用127.0.0.1。启动成功会看到一堆日志输出最后停在 “Appium server listening on...” 就是好了。这个终端窗口要保持开着别关了关了Server就停了。如果你用的是Mac想测iOS的真机还需要装Xcode和WebDriverAgent这块复杂度会明显增高。入门阶段建议先用Android等把业务脚本跑顺了再考虑扩到iOS这样成本最合理。还有一个小提示不要去网上找那种“一键安装包”。Appium这框架的升级节奏快一键包里的版本大概率跟不上驱动版本反而制造出奇怪的兼容问题。自己用npm装一次以后升级驱动和查版本都心里有数。3. Appium Inspector从“看到元素”到“写对定位”3.1 先会看元素树再谈元素定位环境装好之后很多人把Appium Inspector只当截图工具用这其实浪费了一大半价值。Inspector最值钱的功能是把手机屏幕里的控件结构以元素树的形式展示出来——类似网页的HTML结构但对象是App的原生控件。打开Inspector连接你的设备时它要求填四个关键信息Host、Port、Path、Desired Capabilities。Host写127.0.0.1Port写4723对应你启动Server时指定的端口Path一般用默认的/wd/hub就行。Desired Capabilities是重点它本质上是告诉Appium“我要测什么平台、测什么App、以什么模式启动”填不对Session就起不来。一个典型的Android配置长这样{ platformName: Android, platformVersion: 13, deviceName: emulator-5554, appPackage: com.android.settings, appActivity: .Settings, noReset: true, unicodeKeyboard: true, resetKeyboard: true }其中appPackage是App的包名appActivity是你要打开的页面入口。这两个不是猜出来的可以在终端用aapt dump badging apk路径查到也可以先手动打开App再用adb shell dumpsys window | grep mCurrentFocus抓当前在前台的包名和Activity名。以Android系统自带的设置App为例包名通常为com.android.settingsActivity名因版本略有差异需要你实际验证。点“Start Session”之后Inspector会拉起App并展示当前页面的控件树。左侧是真实屏幕的截图右侧是层级树。点选任意控件中间面板会显示这个元素的所有可用属性resource-id、text、content-desc、class name以及自动生成的可选XPath。这套信息就是你写定位符的原材料。3.2 定位策略的选择顺序别一上来就用XPath元素定位是自动化脚本的核心质量指标一个不稳定的定位能在凌晨跑回归的时候让整个流水线蹦掉。很多人刚入手时习惯一条XPath走天下因为Inspector里直接能复制但XPath不是万能的特别是绝对路径。先记住这个优先级resource-id accessibility id对应Android的content-desc class name组合 XPath。能用resource-id就用resource-id它类似HTML里的id属性在页面结构里一般唯一稳定度高。遇到没有id的控件看它有没有content-desc这在一些以图标为主的控件上很常见比如底栏的首页、我的、收藏。如果前两者都没有再用class name加文本配合比如组合定位文本为“登录”的按钮。最后才考虑XPath因为XPath有时会写得又长又脆弱比如/hierarchy/android.widget.FrameLayout/.../android.widget.TextView[2]这种绝对路径只要页面上方多一个Section整个定位就挂了。相对路径会好很多//android.widget.TextView[text登录]还可以组合属性缩短路径//*[resource-idcom.xxx:id/tab and text首页]我的建议是在Inspector里定位元素时不要简单“复制XPath”就完事先看左侧有没有resource-id或content-desc养成这个习惯之后脚本稳定性会明显提升。Inspector还有一个好用的功能是根据你的操作实时录制脚本。你在设备预览区点击元素、输入文本、滑动页面右侧会生成对应的Python或Java代码。对刚入门的人这是最快写出第一段能跑代码的方式。但别依赖录制太久录制出来的代码普遍冗长等你熟悉之后手写反而更干净。4. 让代码跑起来第一个自动化用例的完整过程4.1 用Python写一个能运行的脚本客户端方面Python用Pip安装Appium-Python-ClientJava在Maven里引入java-client依赖我用的是8.6.0以上版本和Appium 2.x配合得很稳。下面这段Python代码可以做“打开系统设置、点击第一项”这类最简单的冒烟操作你把它改成自己的包名、Activity和元素定位就能用from appium import webdriver from appium.options.android import UiAutomator2Options from appium.webdriver.common.appiumby import AppiumBy from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC options UiAutomator2Options() options.platform_name Android options.platform_version 13 options.device_name emulator-5554 options.app_package com.android.settings options.app_activity .Settings options.no_reset True options.unicode_keyboard True options.reset_keyboard True driver webdriver.Remote(http://127.0.0.1:4723/wd/hub, optionsoptions) wait WebDriverWait(driver, 10) first_item wait.until( EC.presence_of_element_located( (AppiumBy.ANDROID_UIAUTOMATOR, new UiSelector().text(WLAN)) ) ) first_item.click() driver.quit()这里有人会问为什么用ANDROID_UIAUTOMATOR而不是普通的AppiumBy.XPATH。当一个元素既没有resource-id也没有content-desc时直接用TextView的文本定位往往更简单。这段代码里的new UiSelector().text(WLAN)是UiAutomator2自己提供的一种定位表达式比XPath的兼容性更好。当然你完全可以在等待里传AppiumBy.XPATH加一个简单路径效果类似。Java版本的写法核心配置是一样的只是语法不同DesiredCapabilities caps new DesiredCapabilities(); caps.setCapability(platformName, Android); caps.setCapability(platformVersion, 13); caps.setCapability(deviceName, emulator-5554); caps.setCapability(appPackage, com.android.settings); caps.setCapability(appActivity, .Settings); caps.setCapability(noReset, true); AndroidDriver driver new AndroidDriver(new URL(http://127.0.0.1:4723/wd/hub), caps);这些Capabilities里面有几个是新手特别容易踩坑的。noReset的作用是告诉Appium“每次启动不用重置App数据”如果不设置某些App每次启动都会回到首次安装的引导页用例自然跑不稳。unicodeKeyboard和resetKeyboard是中文输入问题的解药后面在常见问题里会专门提。4.2 别把sleep当等待三种等待方式的取舍写自动化脚本时最顺手的就是Thread.sleep或者time.sleep——点在元素上先睡三秒再说。如果脚本里有三四个sleep(3)看起来像是“稳了”实际每次跑都浪费至少十秒。更麻烦的是如果页面加载快多余的时间纯粹是白等如果页面偶发卡顿3秒可能还不够脚本照样挂。更合理的方案是显式等待也就是上面代码里用的WebDriverWait。它的机制是给一个总超时时间比如10秒然后每隔一瞬去查看目标元素是否出现出现就马上往下走超时还没出现就抛异常。这样脚本整体节奏快且稳。还有一种是隐式等待implicitly wait在Driver初始化时设置一次对所有元素查找生效。但隐式等待不能解决“元素已出现但不可点击”“元素被其它弹窗遮挡”这类问题配合显式等待使用体验更舒服。入门阶段我的建议是全部用显式等待别图省事写sleep。等你不那么担心脚本偶然失败之后再来针对特定场景精简等待时间也不迟。5. 高频报错与排查技巧实录5.1 环境与启动类报错日志第一行最有用第一次启动Session时最容易碰到两类情况一个是SessionNotCreatedException一个是socket hang up。SessionNotCreatedException的原因非常集中Capabilities配置有问题或者uiautomator2驱动没有安装。排查方法很简单先看一眼Appium Server终端窗口打印的完整错误信息它通常会直接提示你哪一段Capabilities不被接受。我遇到过最离谱的版本是platformVersion写错——模拟器是Android 13配置里却写了“12”Session死活起不来改对就秒过。socket hang up听起来很吓人解决思路其实很朴素。这通常是Appium Server和设备之间的长连接断开造成的常见原因是设备锁屏了、USB线松了、或者开启了多个adb进程。搜这个报错的时候别一头扎进代码逻辑先做三件事看一眼设备屏幕是不是还亮着跑一遍adb devices确认设备在线把Server重启一下。还有一个经典的环境冲突就是电脑上装了多个版本的adb比如Android Studio自带一个、某模拟器又带一个启动时提示 “adb server version doesnt match client”。解决方法是统一PATH里adb的来源最好只留Android SDK的platform-tools然后执行adb kill-server、adb start-server重置一下。5.2 运行与定位类报错九成是定位和时机问题脚本能启动Session反而开始花式失败这是最让大家头疼的阶段。我整理了一张日常排查表按遇到频率排序报错场景常见原因处理办法元素找不到、超时退出定位符写错或页面还没加载完确认Inspector里的属性与代码一致改用显式等待element click intercepted目标被弹窗或悬浮按钮挡住先处理弹窗或改用坐标点击方案中文输入成功但乱码键盘事件编码异常Capabilities加unicodeKeyboard和resetKeyboardSession启动后设备无响应内存不足或App崩溃重启模拟器检查设备内存看adb logcat日志同一脚本偶尔过/偶尔挂动态内容或接口请求导致布局变化避免绝对路径XPath改更稳定的id或文本定位排查这类问题有一个通用方法论先看Appium Server日志它会打印实际收到的HTTP请求和响应再看设备的页面现状用adb shell uiautomator dump把当前界面的XML拉下来对比。很多时候脚本里的定位符看着对但实际页面出现了两个相同文本的控件Appium点错了目标就会表现为“时而成功时而失败”。我在团队里给新人定的规矩是报错顺序永远是“日志 - 屏幕现状 - 定位符复验”跳过前两步直接改代码大概率是在瞎猜。6. 从我自己的角度入门后期要注意什么6.1 稳定性比代码量更重要先做好“少挂”再追求“多跑”很多同学把大量时间花在写新的用例上跑得多了才发现维护成本全压在“每个用例在哪个环节偶尔挂一次”上。我自己经历过这样的阶段用例一百多条每次回归总有一两条随机失败查了半天发现全是等待时间不够、元素被弹窗挡住、或者某个XPath写得太脆。入门到进阶的分水岭不是你会写多少种操作手势而是你有没有能力把脚本跑稳定。一些细节会极大影响稳定性比如启动后等待一个关键元素而不是固定睡五秒每次点击前先确认元素可见且可点脚本结束后做适当的用例清理避免影响下一条用例的状态。这些都是踩过几次坑之后才会真正重视的经验。6.2 进阶路线的推荐顺序和我的建议跑通一个脚本之后我建议按这个顺序往深处走先扎实掌握原生控件的常用操作点击、输入、滑动、等待、断言再处理需要跨App的跳转逻辑和多设备并发问题然后研究WebView/H5场景的切换Appium配合Chromedriver最后才是把用例组织成框架比如Page Object模式、接入CI流水线生成稳定报告。我也一直跟新手强调Appium官方文档更新速度很快网上教程很容易过时。你别在评论区追着老教程问“为什么我这样写报错”先看一眼自己用的Appium版本是什么很多答案自己就浮现了。如果你还在入门初期卡壳我最后给一个建议把“跑通一个最简脚本”当作唯一目标别一上来就贪多求全。环境、定位、等待这三件事弄明白你的移动端自动化就算真正上路了。后面那些花哨的技术点都是在这个基础上长出来的。
返回列表