尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Appium移动端自动化测试实战:从环境搭建到框架封装

Appium移动端自动化测试实战:从环境搭建到框架封装 1. 为什么我开始认真写Appium这套东西提到Appium干过移动端测试的朋友应该都不陌生。我最早接触它的时候还是在Android 4.4横行的年代那时候自动化测试圈子里的主流选择是Robotium和MonkeyRunnerAppium还只是个小众框架。但我当时在项目里踩了太多Native控件和WebView控件混在一起没法统一处理的坑于是认真调研了一圈最后决定全面转向Appium。先说结论Appium真正吸引我的地方不是它跑得多快、脚本写得多炫而是它把“跨平台”和“多语言”这两件最折磨测试开发的事给做了统一。同一套业务逻辑Android和iOS可以共享绝大部分代码而且你不需要为了写脚本去学一门新语言——Java、Python、Ruby、JavaScript都可以直接上手。这对于团队里既有Java后端背景、又有Python脚本功底的测试同学来说简直是救命稻草。这个教程不会只停留在“怎么装环境、怎么点按钮”的层面我更想把这几年来实际项目中踩过的坑、验证过的方案、以及一套真正能跑起来的落地流程一并整理出来。无论你是刚转行做测试的小白还是已经在用其他框架想迁移过来的老兵这篇文章的实操步骤和排查思路应该都能给你节省不少时间。2. 开始之前Appium到底解决了什么问题2.1 自动化测试在移动端的核心矛盾先聊一个比较基础但很关键的问题为什么移动端自动化测试这么难做我见过很多团队前一个月还好好的后一个月维护成本直接压垮了整个测试组。核心矛盾其实就三个字碎片化。这里说的碎片化不只是手机品牌多、屏幕尺寸杂更重要的是技术栈的碎片化。同一个App里Android端有原生页面、有H5页面、甚至还有Flutter或者React Native渲染的页面。如果用一个测试框架只能处理原生控件那当你走到WebView页面的时候脚本就会当场卡死所有用例全部红掉然后测试组的同学就开始通宵手工回归。Appium的设计初衷很大程度就是来解决这个问题的。它基于WebDriver协议额外扩展了一套Mobile JSON Wire Protocol让你可以用同一套API去操作原生控件、WebView控件甚至是混合应用里的元素。你在PC浏览器上写Selenium的那套思路比如通过XPath找元素、通过id定位按钮、通过sendKeys输入文本到了Appium这套体系里几乎可以无缝迁移过来。2.2 为什么是Appium而不是其他框架说实话现在市面上能选的框架并不少。UiAutomator2是Google官方的方案性能和稳定性其实很好但它绑定了Java语言iOS又用不了XCUITest是苹果家的东西只服务iOSEspresso在Android上很快但也只服务Android。如果你只想写单端的脚本这些原生框架完全够用但一旦想让一套团队技能同时覆盖双端它们就变成一个很尴尬的存在。Appium则把“Client代码”和“服务端执行”彻底解耦。你在测试机上运行的是Appium Server它通过监听4723端口接收来自客户端的命令然后针对不同平台把这些命令转换成对应的自动化指令。这意味着前端无论用什么语言去写最终都是走HTTP请求到服务端服务端再去驱动设备干活。这个架构虽然多了一层网络开销带来了大概几十毫秒的额外延迟但在当前这种硬件性能和设备响应速度条件下这点损耗完全可以接受换来的是统一的编程模型和跨平台能力。2.3 一个核心概念先搞明白SessionAppium整个工作流程如果只记一个词那就是Session。你可以把它理解成“一场测试活动的上下文”。客户端发起Desired Capabilities配置服务端接收这些配置后根据配置去拉起指定App然后返回一个Session ID。之后你做的所有查找元素、点击、滑动、输入操作都必须带上这个Session ID服务端才能知道这些命令要作用在哪台设备、哪个App上。我见过很多新手在配置阶段就卡住了Caps写了一大堆但是没弄明白每个参数的意义。其实核心的也就那么几个platformName告诉服务端你要测Android还是iOS。deviceName虽然对Android没有强制约束但最好填adb devices看到的序列号方便定位设备。appPackage / appActivity指定要启动的App及入口Activity这是Android平台最关键的参数。noReset如果设为trueAppium不会在每次测试前清空应用数据。这个参数在调试阶段特别重要否则你每次都要重新走一遍引导页和登录流程能把人折磨疯。等你理解了Session后面所有的脚本编写其实都是在和这个Session打交道。所以不要一上来就背API先把会话机制搞清楚后面就顺了。3. 完整环境搭建每一步都给你踩坑避雷3.1 需要的软件清单Appium这玩意它不是一个单独的安装包装完就万事大吉的。整个链路涉及的东西比较多我列一份我目前Windows笔记本上实际在用的组合你照着装就行版本不一定完全一致但建议接近软件版本建议用途说明Java JDK1.8 或 11Android SDK编译和Appium Server运行依赖Android SDKAPI 30 及以上adb工具、构建工具、平台工具Node.js12 或 14 LTSAppium Server的运行时Appium Desktop2.x自带Server和Inspector可视化工具Appium Inspector最新版元素定位辅助工具Python3.6我的脚本语言用于编写测试用例Appium-Python-Client2.xPython客户端的SDK夜神 / MuMu / 官方模拟器任意Android模拟器建议API 28以上Appium-Python-Client2.x客户端SDK3.2 环境变量的坑十个人里八个栽在这安装完JDK和Android SDK之后接下来就是配置环境变量。这也是我见过新手最容易卡壳的地方而且报错信息往往很模糊比如在cmd里输入adb直接提示“不是内部或外部命令”。这个问题的原因只有一个环境变量没配好cmd找不到adb.exe的路径。Android SDK的环境变量需要配置这么几项ANDROID_HOME你的SDK安装路径比如 D:\Android\Sdk PATH新增%ANDROID_HOME%\platform-tools PATH新增%ANDROID_HOME%\tools PATH新增%ANDROID_HOME%\build-tools\30.0.3Java部分配置JAVA_HOME指向JDK安装目录然后在PATH里加入%JAVA_HOME%\bin。配置好之后别急着往下走先打开一个全新的cmd窗口分别输入以下命令验证java -version adb --version node -v只要这三条命令都能正常输出版本号说明基础环境已经通了。如果哪一步没有输出就回头检查对应的环境变量路径这一步偷懒后面跑脚本的时候会报出一堆无法理解的错误。3.3 安装Appium Server的两种方式Appium Server的安装路径有两条一是在Appium Desktop的界面里直接启动Server二是通过npm命令行安装。我个人的建议是调试阶段用Appium Desktop因为它自带一个可视化界面能直接看到Server的日志输出和监听状态但如果你打算写脚本做持续集成那就必须用npm安装的Appium因为命令行方式可以被脚本直接拉起CI环境里不需要GUI。npm install -g appium appium --version安装完之后你在cmd里敲appium看到listener started on 0.0.0.0:4723这行日志说明Server已经成功启动了。这里的4723就是Appium Server的默认端口所有客户端请求都会发到这个端口上。顺便提一句如果npm安装速度很慢可以考虑把registry切换到国内源npm config set registry https://registry.npmmirror.com装完之后如果还嫌慢那大概率是网络链路问题等一等就行不要反复去卸载重装反而容易搞出环境残留问题。3.4 Android模拟器与真机怎么选模拟器这边Google官方的AVD速度和稳定性都比较均衡但我个人日常更常用的是夜神或MuMu这类第三方模拟器原因只有一点在国内复杂网络环境下官方模拟器拉取镜像经常失败第三方模拟器直接下载安装包就能用省心不少。不过第三方模拟器有一个坑默认情况下adb可能识别不到设备。这是因为模拟器监听的端口不是默认的5555。解决方法是手动连接模拟器端口adb connect 127.0.0.1:62001不同模拟器对应的端口不一样夜神是62001MuMu是7555具体可以在模拟器设置里查看。连接成功后输入adb devices应该能看到127.0.0.1:62001 device这样的状态。这一步如果没做Appium Server启动后会报“No devices found”错误测试根本跑不起来。真机调试的话需要打开开发者选项里的“USB调试”并且安装对应厂商的USB驱动。现在手机厂商普遍做了随机MAC地址的机制导致每次插拔手机adb设备号会变化建议在代码里通过adb devices动态获取设备号而不是写死。4. Desired Capabilities 配置脚本能跑起来的前提4.1 必须弄懂的核心参数Desired Capabilities可以理解成“启动会话的钥匙串”。你告诉Appium Server需要启动什么平台、什么App、以什么模式执行服务端才能正确拉起环境。配置不对后面所有步骤全部白搭而且报错信息经常是让人一头雾水的。这是我在Android模拟器上跑通的一套基础配置desired_caps { platformName: Android, deviceName: 127.0.0.1:62001, appPackage: com.example.app, appActivity: .MainActivity, noReset: True, unicodeKeyboard: True, resetKeyboard: True }platformName和deviceName前面说过了重点说一下appPackage和appActivity怎么拿。很多人一开始都会在这里卡住不知道自己的应用这两个值应该填什么。这里有一个非常实用的命令# 先将App在模拟器或真机上启动 adb shell dumpsys window | grep mCurrentFocus执行之后输出的结果里会显示类似mCurrentFocusWindow{... com.example.app/.MainActivity}的内容斜杠前面就是appPackage后面就是appActivity。这个方法是190%可靠的比在源码里翻AndroidManifest.xml快得多。4.2 noReset 和 unicodeKeyboard 是调试阶段的保命符如果你是在开发阶段调试脚本noReset一定要设为True。不然每跑一次用例Appium都会清除App的数据你的登录状态、引导页开关、推荐算法缓存全部被清空每次都要从头走一遍流程这感觉谁用谁知道。unicodeKeyboard和resetKeyboard这两个参数主要是为了解决中文输入问题。Android原生环境的输入法有时候接不住从Appium发送的中文字符需要先调用系统自带的Unicode输入法接管然后等输入完成之后再恢复原状。这两个参数可以一并设为True基本可以规避掉90%以上的中文输入坑。4.3 报错了两行泪常见配置错误速查配置阶段最容易遇到的报错大致有这几类“Parameters were incorrect”通常是desired_caps里写了不支持的参数名或者参数值格式不对仔细对照官方文档检查拼写。“No such file or directory”如果你指定了app字段指向本地apk但是这个路径不存在Appium Server会直接抛错。建议在项目里建一个apps目录统一存放测试包。“Original error: Could not find a connected Android device.”设备没有正确连接。用adb devices看看设备状态是不是device如果是unauthorized需要在手机上点一下“允许USB调试”弹窗。配置这个环节我个人的建议是不要图省事把所有参数一次性写完再启动而是先写一个最小化配置确认Session能起来、App能拉到前台再逐步增加参数。这样出了问题定位的范围会小很多。5. 用Python写第一个自动化脚本5.1 安装客户端库接下来的所有示例我都用Python来写因为它在测试行业的普及度实在太高而且语法简洁适合快速迭代。先安装Appium的Python客户端库pip install Appium-Python-Client注意这里装的是Python Client库不是Appium Server本身。Server在上面已经装过了这两个东西是独立存在的新手经常会搞混。5.2 第一个脚本打开App并点击一个按钮装好之后写一个最基础的脚本from appium import webdriver import time desired_caps { platformName: Android, deviceName: 127.0.0.1:62001, appPackage: com.example.app, appActivity: .MainActivity, noReset: True } # 连接Appium Server启动会话 driver webdriver.Remote(http://127.0.0.1:4723/wd/hub, desired_caps) time.sleep(3) # 通过resource-id定位元素并点击 element driver.find_element_by_id(com.example.app:id/btn_start) element.click() time.sleep(2) # 验证页面是否跳转成功 assert 成功跳转 in driver.page_source # 关闭会话 driver.quit()这段代码的逻辑很简单但它示范了Appium测试脚本的完整生命周期建立连接、启动会话、查找元素、执行操作、验证结果、关闭会话。你可以在这个骨架上不断扩展加上断言、日志、异常处理慢慢就会形成一个完整的测试框架。5.3 定位元素的几种姿势推荐优先级一次说清楚自动化测试里元素定位是日常写脚本时最频繁的操作也是最容易脆弱的环节。前端稍微改个id或者布局重构一下定位器可能就失效了。我根据自己的实战经验把定位方式的优先级从高到低排个序resource-id定位Android原生控件最稳定可靠形如com.example.app:id/btn_start首选。accessibility idcontent-desc可访问性属性在Android上对应contentDescription适合有做无障碍适配的应用。XPath文本定位比如//android.widget.TextView[text登录]优点是灵活但性能差、维护成本高不建议在循环里大量使用。class name定位按控件类型定位比如android.widget.EditText但同类型控件可能有很多个通常需要配合下标使用能用但容易乱。UIAutomator定位Android平台的进阶玩法可以直接写UI Automator语法比如new UiSelector().text(确认)比较强大但调试起来相对复杂。我在实际项目里的经验是优先保证元素有稳定的id或content-desc写脚本的时候就会非常清爽。如果你的App还没做可测试性改造也没关系可以要求开发帮忙给控件补上资源id这本身就是测试驱动开发的一部分。5.4 一个业务流程的完整脚本示例单点击一个按钮没什么感觉我拿一个真实的登录场景来演示。假设App的登录页有两个输入框和一个登录按钮输入账密后点击登录预期跳转到首页from appium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from appium.webdriver.common.mobileby import MobileBy import time desired_caps { platformName: Android, deviceName: 127.0.0.1:62001, appPackage: com.example.app, appActivity: .LoginActivity, noReset: True, unicodeKeyboard: True, resetKeyboard: True } driver webdriver.Remote(http://127.0.0.1:4723/wd/hub, desired_caps) driver.implicitly_wait(10) # 输入账号 account_input driver.find_element(MobileBy.ID, com.example.app:id/et_account) account_input.clear() account_input.send_keys(test_user_001) # 输入密码 pwd_input driver.find_element(MobileBy.ID, com.example.app:id/et_password) pwd_input.clear() pwd_input.send_keys(Abc123456) # 点击登录 login_btn driver.find_element(MobileBy.ID, com.example.app:id/btn_login) login_btn.click() # 显式等待等待首页元素出现 try: home_element WebDriverWait(driver, 10).until( EC.presence_of_element_located((MobileBy.ID, com.example.app:id/tv_home_title)) ) print(登录成功已进入首页) except Exception as e: print(登录失败页面未跳转) print(driver.page_source) finally: driver.quit()这里有几个值得一说的小细节。第一implicitly_wait(10)设了全局隐式等待所有元素查找都会等待最多10秒这样可以在元素加载稍微慢一点的情况下尽量避免NoSuchElementException。第二登录按钮点击后页面跳转是需要时间的用WebDriverWait显式等待首页元素出现比硬编码time.sleep(5)要健壮得多。我在写脚本的时候显式等待优先级永远高于time.sleep这是一个能让脚本稳定性提升一个档次的好习惯。5.5 滑动、点击坐标等特殊操作除了常规的点击和输入移动端测试里还有两个高频操作是Web自动化里不太碰到但Appium里非常常用的滑动和坐标点击。# 从点(x1,y1)滑到点(x2,y2)整个过程耗时300毫秒 driver.swipe(x1, y1, x2, y2, duration300) # 通过坐标直接点击手机分辨率不同坐标也会变化所以只建议临时用 driver.tap([(x, y)], duration100)需要特别提醒的是坐标点击是一个“能不用就不用”的操作。只要元素能通过id定位到就用id因为坐标会随着设备分辨率变化而失效。但如果你的需求是滑动轮播图、左滑删除、下拉刷新这类没有现成控件属性的操作用坐标就是最直接的方式。还有一个获取屏幕尺寸的小技巧可以用来按比例计算滑动起点和终点size driver.get_window_size() start_x size[width] // 2 start_y int(size[height] * 0.8) end_x size[width] // 2 end_y int(size[height] * 0.2) driver.swipe(start_x, start_y, end_x, end_y, duration500)这样写脚本在不同分辨率设备上都能正常滑动不用为每台设备单独调参。6. 用好Appium Inspector元素定位的效率工具6.1 为什么要用可视化工具很多新手刚开始写Appium脚本的时候有个误区对着App猜元素属性感觉这个位置像是个Button然后就盲写代码跑不起来再慢慢试。这种方式效率太低了。正确的姿势应该是先用Appium Inspector打开你的App看一眼控件树确定你要操作的元素长什么样、该用什么属性去定位然后再写脚本。Appium Inspector在Appium 2.x里默认是包含的直接在Appium Desktop里点击放大镜图标就能打开。它连接上Session之后左边是屏幕截图右边是控件层级树点击某个控件还能看到这个控件的所有属性包括resource-id、class、text、bounds等。有了这些属性写定位器的准确率几乎是100%。6.2 用Inspector快速拿到定位信息打开Inspector的基本步骤是启动Appium Server。在Appium Desktop主页点击Inspector按钮。输入和脚本一致的Desired Capabilities配置。点击Start SessionInspector会自动拉起你的App并生成当前页面的控件树。点击你想定位的元素右侧面板会显示完整属性。这个流程唯一要注意的是Inspector启动的Session和你脚本后续启动的Session是两回事不要同时操作否则两个会话会互相干扰导致App被来回重启。我建议先在Inspector里完成元素侦察然后退出Inspector再运行你的测试脚本。6.3 Inspector常见的连接问题我见过太多人在Inspector这一步翻车了主要症状有Session创建超时大概率是desired_caps填错尤其注意appPackage和appActivity的大小写大小写错误几乎无法直接看出问题但就是连不上。屏幕截图一直是黑屏模拟器的GPU渲染和Appium的截图机制冲突可以尝试在模拟器设置里把GPU模式改成软件渲染。控件树为空确认你选的platformName和实际设备一致有时候Inspector会默认连上次的Session配置导致连到了不存在的设备上。Inspector用熟练之后你会发现写元素定位这事基本就是“抄作业”照着控件属性写就行根本没多少技术含量。7. 把脚本变成一个能跑起来的测试框架7.1 从脚本到框架为什么要做封装如果只是测试几个核心场景那写脚本就够了。但一旦用例数量增长到几十条上百条直接裸写脚本就会面临三个问题大量重复的初始化代码、元素定位信息散落在各个用例里、用例失败时连日志都捞不到。这时候就需要做框架层面的封装。我比较推荐的分层结构是把设备连接、启动App、关闭会话这些公共逻辑抽到BaseDriver里把页面操作封装成Page Object类把测试用例写在专门的test目录下断言和报告用pytest来组织。# base_driver.py from appium import webdriver class BaseDriver: def __init__(self, desired_caps): self.driver webdriver.Remote(http://127.0.0.1:4723/wd/hub, desired_caps) def find(self, locator): return self.driver.find_element(*locator) def click(self, locator): self.find(locator).click() def input_text(self, locator, text): element self.find(locator) element.clear() element.send_keys(text) def swipe_up(self): size self.driver.get_window_size() start_x size[width] // 2 start_y int(size[height] * 0.8) end_y int(size[height] * 0.2) self.driver.swipe(start_x, start_y, start_x, end_y, duration500) def quit(self): self.driver.quit()这样封装之后写用例的地方基本就是在描述业务操作本身代码可读性和维护性都提升了很多。7.2 Page Object模式塞进项目里很香Page Object模式几乎是测试框架的标准姿势了。核心思想其实很简单一个页面对应一个类页面上所有操作逻辑都放在这个类里测试用例只负责编排动作和验证结果不直接接触元素定位细节。# pages/login_page.py from appium.webdriver.common.mobileby import MobileBy class LoginPage: ACCOUNT_INPUT (MobileBy.ID, com.example.app:id/et_account) PWD_INPUT (MobileBy.ID, com.example.app:id/et_password) LOGIN_BTN (MobileBy.ID, com.example.app:id/btn_login) def __init__(self, driver): self.driver driver def input_account(self, account): element self.driver.find_element(*self.ACCOUNT_INPUT) element.clear() element.send_keys(account) def input_pwd(self, pwd): element self.driver.find_element(*self.PWD_INPUT) element.clear() element.send_keys(pwd) def click_login(self): self.driver.find_element(*self.LOGIN_BTN).click()这样做的最大好处是当登录页的UI从“账号密码框登录按钮”改成“验证码登录”或者“一键登录”我只需要更新LoginPage这一个类所有关联的测试用例都不需要改动。如果你的App迭代频繁UI动不动就变Page Object模式能帮你省出大量的维护时间。7.3 pytest 数据驱动让用例量跑起来框架最后一个拼图是测试执行层。我推荐用pytest它天生支持fixture、参数化和丰富的断言并且生态里有allure-pytest可以直接生成漂亮的可视化测试报告。test_cases/ ├── test_login.py ├── test_order.py └── conftest.py在conftest.py里定义一个设备初始化的fixtureimport pytest from appium import webdriver pytest.fixture(scopemodule) def driver(): desired_caps { platformName: Android, deviceName: 127.0.0.1:62001, appPackage: com.example.app, appActivity: .LoginActivity, noReset: True } driver webdriver.Remote(http://127.0.0.1:4723/wd/hub, desired_caps) yield driver driver.quit()然后用参数化来跑多组数据import pytest from pages.login_page import LoginPage class TestLogin: pytest.mark.parametrize(account,password, [ (user01, Pass123), (user02, Pass456) ]) def test_login(self, driver, account, password): login_page LoginPage(driver) login_page.input_account(account) login_page.input_pwd(password) login_page.click_login() assert 登录成功 in driver.page_source跑上面的用例只需在项目根目录执行pytest -v --alluredir ./report这一套流程下来你的自动化测试已经从“脚本”升级为“框架”了。之前那种一条用例写一个月、上线两个月全废气的情况会得到很明显的改善。8. 常见问题与排查技巧实录8.1 高频报错排查表做Appium的时间长了会发现大部分报错都集中在几个固定场景里。我整理了一份排查速查表基本覆盖了我日常工作中80%以上的问题报错信息可能原因处理方式Error: Could not find a connected Android device设备未连接或adb未识别adb devices检查设备状态确认设备正常模拟器则先adb connect 127.0.0.1:端口Element not found元素定位器失效或页面尚未加载完成优先用Appium Inspector查看最新的控件id配合显式等待SessionNotCreatedExceptiondesired_caps配置有误检查appPackage、appActivity是否正确platformName拼写是否正确Unknown command: wd/hubAppium版本和客户端版本不匹配Appium 2.x与较老客户端库存在兼容问题升级Appium-Python-Client到2.xTimeoutExceptionApp启动太慢或页面加载太久提高WebDriverWait的超时时间或者检查noReset配置adb server version doesnt match this client多个adb版本冲突在环境变量里统一指定一个SDK版本或结束adb进程后重新启动8.2 模拟器和真机之间切换时容易踩的坑不少团队是开发阶段用模拟器回归阶段用真机这就会遇到几个典型的坑。模拟器上跑得好好的用例换到真机上第一反应就是满屏失败。最常见的原因有两个第一分辨率不同。你在模拟器上滑动距离是写死的真机屏幕更大指定距离可能就够不到目标元素。所以在写滑动操作的时候尽量基于get_window_size()做比例计算而不是写死像素数。第二权限弹窗。模拟器很多系统弹窗是默认关掉的真机上跑用户协议弹窗、位置权限弹窗、通知权限弹窗一个接一个地冒出来。遇到这种情况要么在用例里写一个处理弹窗的通用函数比如判断当前页面有没有“允许”按钮有就点掉要么在设备初始化阶段统一预授权。8.3 测试不稳定先从这五个方向排查测试不稳定业界叫“flaky tests”这几乎是所有自动化测试团队绕不开的痛点。同一个用例这次跑通过了下次就跑挂了而且挂的位置还不一样。我个人的排查顺序是这样先看元素加载是否足够快。把隐式等待设为10秒或者把关键的页面跳转改成显式等待。再看元素是否唯一。同一个页面上如果存在多个相同id或相同文本的控件find_element只会返回第一个这时候如果UI顺序变化脚本就会点错。然后看输入框有没有清空。不清空输入框直接send_keys后面的内容会接在已有内容后面实测这种问题很隐蔽。接着看App的前后状态。如果上一个用例没有正常退出残留页面会直接导致下一个用例定位不到元素。最后检查设备状态。跑太久的内存占用、过热降频、后台网络切换都会导致测试中断。8.4 一个小技巧日志和截图能救你于水火用例失败不可怕可怕的是失败了你不知道它为什么挂。我强烈建议在用例的finally块里强制截屏def test_something(driver): try: # 测试步骤 pass except Exception: # 失败时截屏 driver.save_screenshot(./screenshots/test_something_failed.png) raise finally: # 无论如何都要把当前页面源码保存下来 with open(./logs/test_something_page_source.xml, w, encodingutf-8) as f: f.write(driver.page_source)页面源码XML文件会记录当前页面的完整控件树这个文件的价值在于即使截图黑屏或者被系统弹窗挡住了你依然可以从XML里看到页面到底发生了什么。9. 我把这个教程落到实际项目的体会写到这里最后聊点实在的。我从决定用Appium到把一个项目的关键链路全部自动化前前后后经历了大概两个月。第一个月的感受是“这也能报错”第二个月开始才逐渐摸清它的脾气等到第三个月脚本已经能稳定跑完所有核心回归测试我开始越来越觉得这套工具值得投入。如果让我给刚入坑的你一条建议那就是不要急着用框架去炫技先把最基本的“启动App、点击、输入、断言、退出”这几个动作跑得滚瓜烂熟。然后接Page Object模式再接数据驱动再接持续集成一步一步来。另一个很深刻的体会是Appium本身并不难真正难的是你对自己产品业务逻辑的理解。自动化测试的维护成本本质上等于业务变化成本和测试代码耦合度之间的乘积。你把业务理解得越透彻写出来的测试结构就越贴近真实场景维护的时候就越不容易被产品迭代打乱节奏。最后分享一个小扩展方向现在的Appium已经可以通过driver.execute_script(mobile: shell, ...)直接执行adb shell命令这很有用。比如你可以在测试里用shell命令去设置系统时区、修改网络状态、模拟弱网这些高级用法能让你离“完美还原线上场景”更近一步。等基础功能玩透了尝试往这个方向深入应该会很有意思。
返回列表