Appium+Python+雷电模拟器:移动端自动化测试入门实战指南
1. 项目概述:为什么选择这套组合拳?
如果你刚接触移动端自动化测试,面对市面上五花八门的工具和框架,可能会有点懵。我刚开始那会儿也这样,直到我反复折腾、踩了无数坑之后,才最终把“Appium + Python + 雷电模拟器”这套组合固定为我的入门和主力方案。这不是因为它最“高大上”,而是因为它对新手最友好、成本最低、生态最成熟,能让你用最小的代价跑通第一个自动化脚本,并建立起持续学习和迭代的信心。
简单来说, Appium 是一个开源的、跨平台的移动端自动化测试框架,它最大的魅力在于“一次编写,到处运行”。你写一套脚本,理论上可以测试Android、iOS、甚至Windows桌面应用。它底层基于WebDriver协议,这意味着如果你有Selenium做Web自动化的经验,上手会非常快。 Python 就不用多说了,语法简洁、库丰富、社区活跃,是自动化测试领域的“普通话”,几乎所有的测试框架都提供了Python客户端,学习资源和第三方支持是最多的。而 雷电模拟器 ,则解决了真机测试的硬件门槛和效率问题。它运行在电脑上,性能稳定、调试方便(直接截屏录屏)、可以多开并行,对于功能测试和回归测试来说,是绝佳的沙盒环境。
这套组合的核心价值在于,它构建了一个从零到一的完整闭环:用雷电模拟器提供稳定、可复现的测试环境;用Appium作为驱动这个环境的“遥控器”;用Python编写灵活、易读的测试逻辑。你不需要准备多台真机,不需要担心测试过程中的电量、网络波动,可以专注于测试用例的设计和脚本的编写本身。对于个人学习者、中小团队或者项目初期的快速验证阶段,性价比极高。
2. 环境搭建:一步一坑的避雷指南
环境搭建是劝退新手的第一个拦路虎。网上教程很多,但版本兼容性问题、路径配置错误、依赖缺失等问题层出不穷。下面我以Windows系统为例,带你走一遍最稳妥的搭建流程,并附上我踩过的坑和解决方案。
2.1 Python与IDE环境准备
首先确保你的电脑上安装了Python。我强烈建议使用Python 3.8或3.9版本,这是目前与各类库兼容性最好的版本。不要追求最新版,很多库的更新会滞后。
-
安装Python :从Python官网下载安装包。安装时务必勾选“Add Python to PATH”,这样可以在命令行直接使用
python和pip命令。安装完成后,打开命令提示符(CMD)或PowerShell,输入python --version和pip --version验证是否成功。 -
选择IDE :PyCharm和VSCode是两大主流。PyCharm是专为Python设计的,开箱即用,对项目管理、虚拟环境、调试的支持非常完善,适合新手。VSCode更轻量,通过安装Python插件也能获得很好的体验,适合喜欢折腾和自定义的用户。我个人更推荐新手直接用PyCharm Community(免费版),省心。
-
创建虚拟环境 :这是一个好习惯,能为每个项目隔离Python包,避免版本冲突。在项目目录下,打开终端执行:
python -m venv venv然后激活它(Windows):
.\venv\Scripts\activate激活后,命令行前缀会显示
(venv),表示你正在虚拟环境中操作。
2.2 雷电模拟器安装与基础配置
雷电模拟器直接官网下载安装即可,建议安装64位版本。安装后启动,你会看到一个类似手机的界面。
这里有几个关键配置点,直接影响后续Appium的连接和测试:
-
开启开发者选项与USB调试 :这和真机一样。进入模拟器的“设置” -> “关于平板电脑” -> 连续点击“版本号”7次,开启开发者选项。返回上级菜单,进入“开发者选项”,开启“USB调试”。这是Appium能够连接和控制模拟器的前提。
-
修改模拟器设置(可选但重要) :
- 性能设置 :根据电脑配置,将CPU和内存调高(如4核,4096MB),运行会更流畅。
- 分辨率设置 :建议设置为
1080x1920 (480dpi),这是一个非常通用的手机分辨率,方便脚本在不同设备间迁移。 - 网络设置 :确保网络通畅。如果你需要抓包(比如用Burp Suite分析测试过程中的网络请求),可以将网络连接模式设置为“桥接模式”,并手动配置代理。但这属于进阶内容,入门阶段可以先不管。
-
记住模拟器的ADB连接信息 :启动模拟器后,打开命令行,进入雷电模拟器的安装目录(默认类似
C:\Program Files\ldplayer\),找到adb.exe。在同目录打开命令行,输入adb devices。你会看到一个设备号,格式通常为127.0.0.1:5555。这个地址和端口号就是Appium要连接的目标。
注意 :很多教程会让你安装独立的Android SDK并配置其ADB,这当然可以。但对于雷电模拟器,更简单的方法是直接使用它自带的ADB。但要小心“ADB冲突”,如果电脑上同时有多个ADB(比如Android Studio的),可能会导致端口占用或设备列表混乱。一个稳妥的办法是,将雷电模拟器安装目录下的
adb.exe路径添加到系统环境变量PATH的最前面,确保命令行优先调用它。
2.3 Appium Server与Client的部署
Appium分为Server和Client两部分。Server是一个服务,负责接收我们编写的测试脚本(Client)发来的指令,并将其翻译成模拟器或真机可以理解的操作。Client就是我们的Python脚本,使用 Appium-Python-Client 这个库来和Server通信。
-
安装Appium Server :有两种方式。
- 桌面版(Appium Desktop) :对于新手,我强烈推荐先从桌面版开始。它集成了Server和Inspector(一个用于定位元素的图形化工具),界面友好。从Appium官网下载安装即可。启动后,只需要点击“Start Server”按钮,一个服务就在本地(默认
http://127.0.0.1:4723)跑起来了。 - 命令行版(Appium via NPM) :需要先安装Node.js,然后通过npm安装:
npm install -g appium。安装后,在命令行输入appium即可启动服务。这种方式更灵活,适合集成到CI/CD流水线中,但初期调试不如桌面版直观。
- 桌面版(Appium Desktop) :对于新手,我强烈推荐先从桌面版开始。它集成了Server和Inspector(一个用于定位元素的图形化工具),界面友好。从Appium官网下载安装即可。启动后,只需要点击“Start Server”按钮,一个服务就在本地(默认
-
安装Python客户端库 :在你的项目虚拟环境中,执行:
pip install Appium-Python-Client这个库封装了与Appium Server交互的所有协议。
-
安装Appium Inspector(独立版) :Appium Desktop内置的Inspector在较新版本中已被标记为废弃。官方推荐使用独立的Appium Inspector。这是一个独立的应用程序,用于连接设备,查看UI层级结构,定位元素并获取其属性(如
resource-id,xpath,class等),是编写脚本时不可或缺的“眼睛”。务必去官网下载安装。
3. 核心原理与关键配置解析
在开始写代码之前,理解Appium如何工作以及如何正确配置它,能让你在遇到问题时更快地定位原因。
3.1 Appium的工作机制:基于WebDriver的桥梁
你可以把Appium Server想象成一个翻译官。我们的Python脚本(Client)使用WebDriver协议(一种基于HTTP/JSON的协议)向Server发送请求,比如“点击某个按钮”。Appium Server收到请求后,会根据我们提供的“Desired Capabilities”配置,知道我们要操作的是哪个设备、哪个应用。然后,它调用对应平台的底层自动化框架(对于Android是UiAutomator2或Espresso,对于iOS是XCUITest),将这些高级指令转换成设备能执行的原生操作命令。最后,操作结果再通过相同的路径返回给我们的脚本。
为什么是UiAutomator2? 在Desired Capabilities中,你会看到一个参数 automationName: UiAutomator2 。这是Android平台目前推荐且稳定的自动化引擎。相比老旧的 UiAutomator1 ,它支持更丰富的操作(如长按、滑动到元素)、更好的等待策略,并且是Google官方维护的。除非有特殊兼容性问题,否则一律使用 UiAutomator2 。
3.2 Desired Capabilities:与设备对话的“合同”
这是Appium脚本中最重要的部分,它是一组键值对,定义了测试会话的所有要求。你可以把它理解为告诉Appium Server:“嗨,我要测试这样一个应用,在这样一个设备上,请按这些规则来。”
一个连接雷电模拟器,测试其内置“设置”应用的典型配置如下(Python字典格式):
from appium import webdriver
desired_caps = {
# 必填:指定测试平台,这里是安卓
'platformName': 'Android',
# 必填:平台版本,在模拟器“设置-关于”里查看,或通过`adb shell getprop ro.build.version.release`获取
'platformVersion': '9', # 根据你的模拟器安卓版本填写
# 必填:设备名称,通过`adb devices`命令获取
'deviceName': '127.0.0.1:5555', # 雷电模拟器的默认ADB地址
# 必填:自动化引擎,安卓推荐UiAutomator2
'automationName': 'UiAutomator2',
# 必填:要启动的App包名
'appPackage': 'com.android.settings',
# 必填:要启动的App的主Activity名
'appActivity': '.Settings',
# 可选但重要:设置命令超时时间,单位秒
'newCommandTimeout': 60,
# 可选:是否在会话结束后不重置App状态(如不清空数据)
'noReset': True,
# 可选:设置Unicode输入,支持中文输入
'unicodeKeyboard': True,
'resetKeyboard': True,
}
-
appPackage和appActivity:如何获取?有两个方法。一是问开发。二是使用ADB命令:先打开你要测试的App,然后在命令行输入adb shell dumpsys window | findstr mCurrentFocus(Windows),输出结果中/后面的就是appPackage,再后面的就是appActivity。 -
deviceName:对于模拟器,使用adb devices列出的地址即可。对于真机,可以自定义一个易读的名字。 -
noReset:设为True时,Appium不会在测试开始前清除App的数据,这对于测试需要登录状态的连续场景非常有用。设为False则每次都会清空数据,回到初始状态。
3.3 元素定位:UI自动化的基石
自动化测试的本质就是模拟人对UI元素的操作。因此,如何精准地“找到”屏幕上的按钮、输入框等元素,是核心中的核心。Appium支持多种定位策略,和Selenium非常类似。
-
ID定位 (
resource-id) :最优先使用的方式,通常由开发在代码中指定,具有唯一性和稳定性。在Appium Inspector中查看元素的resource-id属性。driver.find_element(AppiumBy.ID, “com.example.app:id/login_button”) -
Accessibility ID定位 (
content-desc) :如果元素有content-desc(内容描述)属性,也可以用它定位。这个属性本意是给无障碍服务使用的,有时开发也会用它。driver.find_element(AppiumBy.ACCESSIBILITY_ID, “登录”) -
XPath定位 :最强大但也最脆弱的定位方式。它通过元素的层级路径来定位。当元素没有ID和Accessibility ID时可以使用,但应尽量避免使用绝对路径(以
/开头),而是使用相对路径和属性组合。# 相对路径结合属性定位 driver.find_element(AppiumBy.XPATH, “//android.widget.Button[@text=‘登录’]”) # 使用部分文本匹配 driver.find_element(AppiumBy.XPATH, “//*[contains(@text, ‘部分文字’)]”) -
Class Name定位 :通过元素的类名定位,如
android.widget.EditText。但通常一个界面上同类元素太多,不唯一,需要结合其他条件或使用find_elements取列表后按索引选择。# 找到所有输入框,取第一个 driver.find_elements(AppiumBy.CLASS_NAME, “android.widget.EditText”)[0] -
Android UiAutomator定位 (UIAutomator2) :这是Android原生提供的定位方式,功能非常强大,可以通过复杂的条件组合来查找元素。
from appium.webdriver.common.appiumby import AppiumBy # 文本匹配 driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().text(“登录”)’) # 多个条件组合 driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().className(“android.widget.Button”).text(“确认”)’)
实操心得 :定位元素的黄金法则是“优先使用ID,其次Accessibility ID,万不得已再用XPath,并尽量使用相对路径和属性组合”。XPath在页面结构变化时极易失效。每次使用Appium Inspector定位时,多观察元素的属性,思考哪种方式最稳定。将定位信息(如ID、XPath)单独管理在一个配置文件中,而不是硬编码在脚本里,是迈向编写可维护测试框架的第一步。
4. 第一个自动化脚本实战:从打开应用到完成操作
理论说再多,不如动手写一行代码。让我们来完成一个最简单的实战:打开雷电模拟器的“设置”应用,进入“无线和网络”菜单,然后返回。
4.1 脚本编写与逐行解读
首先,确保你的雷电模拟器已经启动,并且Appium Server(桌面版或命令行版)正在运行(默认端口4723)。
创建一个新的Python文件,比如 first_test.py 。
# 导入必要的库
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.options.android import UiAutomator2Options
import time
# 1. 定义设备能力配置
# 这里使用新的Options方式,比旧的字典方式更清晰、类型安全
options = UiAutomator2Options()
options.platform_name = ‘Android’
options.platform_version = ‘9’ # 请根据你的模拟器版本修改
options.device_name = ‘127.0.0.1:5555’
options.automation_name = ‘UiAutomator2’
# 我们要测试的是系统设置App
options.app_package = ‘com.android.settings’
options.app_activity = ‘.Settings’
# 设置超时和不清除数据
options.new_command_timeout = 60
options.no_reset = True
# 2. 连接Appium Server并启动会话
# 注意:这里的URL指向本地运行的Appium Server
driver = webdriver.Remote(‘http://127.0.0.1:4723’, options=options)
# 等待2秒,让应用界面完全加载稳定
time.sleep(2)
try:
# 3. 定位并点击“网络和互联网”选项(文本可能因系统语言而异)
# 先通过Appium Inspector找到这个元素的特征。这里假设其文本是“网络和互联网”
network_item = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,
‘new UiSelector().text(“网络和互联网”)’)
network_item.click()
print(“已点击‘网络和互联网’.”)
time.sleep(1) # 等待页面跳转
# 4. 在“网络和互联网”页面,我们可以做更多操作,例如点击“Wi-Fi”
# wifi_item = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,
# ‘new UiSelector().text(“Wi-Fi”)’)
# wifi_item.click()
# print(“已点击‘Wi-Fi’.”)
# time.sleep(1)
# 5. 按返回键,回到设置主页面
driver.back()
print(“已按返回键.”)
time.sleep(1)
except Exception as e:
# 如果出现任何错误(如元素找不到),打印错误信息
print(f“执行过程中出现错误:{e}”)
# 可以在这里截图,方便排查
driver.save_screenshot(‘error_screenshot.png’)
finally:
# 6. 无论成功与否,最后都要关闭会话,释放资源
print(“测试结束,关闭驱动.”)
driver.quit()
逐行解读与注意事项:
- 新的Options方式 :代码中使用了
UiAutomator2Options()来配置能力,这是Appium-Python-Client较新版本推荐的方式,比直接使用字典更规范,能提供更好的代码提示和类型检查。 - 连接驱动 :
webdriver.Remote是建立连接的关键。URL必须和你的Appium Server地址一致。 - 隐式等待 vs 强制等待 (
time.sleep) :脚本中使用了time.sleep,这是一种“强制等待”,会让脚本无条件暂停指定时间。这在快速原型或调试时可以用,但在正式脚本中是非常不好的习惯,因为它会浪费大量时间(即使元素早已加载好)。 最佳实践是使用“显式等待” 。 - 异常处理 :使用
try...except...finally结构是个好习惯。在except中捕获异常并截图,能极大提升调试效率。finally块确保无论测试成功还是失败,driver.quit()都会被调用,关闭会话,避免资源泄露。 -
driver.back():模拟设备的返回键。这是一个非常常用的导航操作。
4.2 优化:使用显式等待提升脚本健壮性
让我们用显式等待来替换那些不稳定的 time.sleep 。显式等待会告诉WebDriver:在抛出“找不到元素”异常之前,持续检查某个条件是否成立(比如元素是否可见、可点击),最多等待一段时间。
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# … 前面的配置和连接代码不变 …
try:
# 创建显式等待对象,最多等待10秒,每0.5秒检查一次条件
wait = WebDriverWait(driver, 10)
# 等待“网络和互联网”元素出现并可点击,然后点击它
network_locator = (AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().text(“网络和互联网”)’)
network_item = wait.until(EC.element_to_be_clickable(network_locator))
network_item.click()
print(“已点击‘网络和互联网’.”)
# 如果需要,同样用显式等待来操作Wi-Fi
# wifi_locator = (AppiumBy.ANDROID_UIAUTOMATOR, ‘new UiSelector().text(“Wi-Fi”)’)
# wifi_item = wait.until(EC.element_to_be_clickable(wifi_locator))
# wifi_item.click()
# print(“已点击‘Wi-Fi’.”)
driver.back()
print(“已按返回键.”)
except Exception as e:
print(f“执行过程中出现错误:{e}”)
driver.save_screenshot(‘error_screenshot.png’)
finally:
print(“测试结束,关闭驱动.”)
driver.quit()
为什么显式等待更好?
- 效率高 :如果元素在2秒内就加载好了,它不会傻等10秒,会立即执行后续操作。
- 健壮性强 :能有效应对网络波动、应用启动速度差异等导致的元素加载时间不确定的问题。
- 代码清晰 :明确表达了你“等待什么条件”,而不是“等待多少时间”。
5. 常见问题排查与实战技巧实录
即使按照步骤操作,你也一定会遇到各种问题。下面是我总结的常见“坑”及其解决方案。
5.1 连接类问题
问题1: adb devices 列表为空,或者找不到 127.0.0.1:5555 设备。
- 可能原因1 :雷电模拟器未启动。确保模拟器已完全启动进入主界面。
- 可能原因2 :ADB冲突。电脑上可能有多个ADB服务在运行(如Android Studio的)。解决:关闭所有可能占用ADB的程序,或在命令行执行
adb kill-server,然后重新执行adb devices。最根本的解决方法是确保环境变量PATH中,雷电模拟器的adb路径在最前面。 - 可能原因3 :模拟器的ADB调试未开启。确认模拟器“开发者选项”中的“USB调试”已打开。
问题2:Appium Server启动失败,或脚本报错 Unable to create a new remote session 。
- 可能原因1 :端口冲突。Appium默认使用4723端口。确保没有其他程序占用该端口。可以通过
netstat -ano | findstr :4723(Windows)检查。 - 可能原因2 :
Desired Capabilities配置错误。仔细检查每一项,特别是platformVersion、deviceName、appPackage、appActivity。deviceName必须和adb devices列出的完全一致。appPackage和appActivity必须正确。 - 可能原因3 :Appium Server版本与Client库版本不兼容。尝试使用相对稳定的版本组合,例如Appium Server 2.x 搭配
appium-python-client的最新稳定版。查看官方文档的版本兼容性说明。
5.2 元素操作类问题
问题3:脚本报错 NoSuchElementException ,找不到元素。
- 可能原因1 :页面尚未加载完成。 解决方案 :使用显式等待(
WebDriverWait)代替硬性等待(time.sleep)。 - 可能原因2 :定位器写错了。 解决方案 :使用Appium Inspector重新捕获元素,核对定位器字符串。特别注意XPath是否因页面动态内容而失效。优先尝试其他定位方式,如ID或Accessibility ID。
- 可能原因3 :元素在WebView或混合应用中。 解决方案 :需要切换上下文(Context)。使用
driver.contexts获取所有上下文,然后切换到对应的WebView上下文(通常名字包含WEBVIEW)再进行操作。这是一个进阶话题,但很常见。 - 可能原因4 :元素在弹窗、下拉菜单或新的Activity中。 解决方案 :确保你的操作(如点击)触发了界面变化后,需要重新定位新界面上的元素。有时需要处理系统弹窗(如权限申请)。
问题4:可以找到元素,但点击( click() )没反应。
- 可能原因1 :元素不可点击。 解决方案 :使用
element_to_be_clickable条件进行显式等待,确保元素是可交互状态。 - 可能原因2 :元素被其他元素(如透明遮罩层)遮挡。 解决方案 :尝试使用TouchAction(旧版)或W3C Actions(新版)提供更精确的点击坐标,或者先处理掉遮挡层。
- 可能原因3 :需要的是“轻触”而不是“点击”,或者需要更复杂的操作(如长按)。 解决方案 :使用
driver.tap([(x, y)], duration)进行轻触,或使用Actions API进行长按、滑动等操作。
5.3 性能与稳定性技巧
- 截图与录屏是救命稻草 :在关键步骤前后、尤其是断言失败或发生异常时,自动截图。Appium提供了
driver.save_screenshot(‘filename.png’)方法。对于复杂问题,可以考虑录屏。 - 使用Page Object模式(PO) :当测试用例越来越多时,不要把定位器和操作逻辑都堆在一个脚本里。将每个页面封装成一个类,页面的元素定位器作为类的属性,页面的操作(如登录、搜索)作为类的方法。这样能使代码结构清晰,易于维护,元素定位器变更只需修改一处。
- 配置
autoGrantPermissions:在Desired Capabilities中设置‘autoGrantPermissions’: True,可以让Appium自动处理应用弹出的运行时权限请求,避免脚本被弹窗打断。 - 处理应用升级/安装弹窗 :自动化安装或启动应用时,可能会遇到“是否升级”、“安装风险提示”等系统弹窗。这些弹窗不属于你的应用,需要特殊处理。可以尝试用ADB命令提前安装,或者在脚本中加入判断和处理这些弹窗的逻辑(通常通过识别弹窗上的“确定”、“安装”按钮文本)。
- 日志分析 :当脚本运行出错时,不要只看Python的报错信息。仔细查看Appium Server的控制台输出日志,里面包含了更详细的底层交互信息,是排查问题的关键。
6. 项目结构与脚本组织入门
当你掌握了单个脚本的编写后,很快就会面临如何管理多个测试用例、测试数据和公共代码的问题。一个好的项目结构能极大提升协作效率和维护性。
一个典型的入门级项目结构可以这样组织:
your_automation_project/
├── config/ # 配置文件目录
│ ├── __init__.py
│ └── config.py # 存放设备配置、App信息、服务器地址等
├── pages/ # 页面对象目录
│ ├── __init__.py
│ ├── base_page.py # 所有Page类的基类,封装公共方法
│ ├── main_page.py # 例如,应用主页的Page类
│ └── login_page.py # 登录页的Page类
├── test_cases/ # 测试用例目录
│ ├── __init__.py
│ ├── test_login.py # 登录功能测试用例
│ └── test_search.py # 搜索功能测试用例
├── utils/ # 工具函数目录
│ ├── __init__.py
│ ├── logger.py # 日志记录工具
│ └── common_actions.py # 封装滑动、截图等公共操作
├── reports/ # 测试报告目录(可自动生成)
├── screenshots/ # 失败截图目录
├── requirements.txt # 项目依赖包列表
└── run_tests.py # 测试运行主入口
简要说明:
-
config.py:集中管理配置,避免硬编码。# config.py class Config: APPIUM_SERVER = ‘http://127.0.0.1:4723’ PLATFORM_NAME = ‘Android’ PLATFORM_VERSION = ‘9’ DEVICE_NAME = ‘127.0.0.1:5555’ APP_PACKAGE = ‘com.example.myapp’ APP_ACTIVITY = ‘.MainActivity’ -
base_page.py:所有页面类的父类,可以封装查找元素的通用方法、日志记录、截图等。# pages/base_page.py from appium.webdriver.webdriver import WebDriver class BasePage: def __init__(self, driver: WebDriver): self.driver = driver def find(self, locator): # 可以在这里加入显式等待和日志 print(f“Finding element with locator: {locator}”) return self.driver.find_element(*locator) -
login_page.py:继承BasePage,封装登录页的所有元素和操作。# pages/login_page.py from appium.webdriver.common.appiumby import AppiumBy from .base_page import BasePage class LoginPage(BasePage): # 元素定位器 username_input = (AppiumBy.ID, ‘com.example.app:id/username’) password_input = (AppiumBy.ID, ‘com.example.app:id/password’) login_button = (AppiumBy.ID, ‘com.example.app:id/login’) # 页面操作方法 def login(self, username, password): self.find(self.username_input).send_keys(username) self.find(self.password_input).send_keys(password) self.find(self.login_button).click() -
test_login.py:使用Page Object来组织测试用例,清晰易懂。# test_cases/test_login.py import pytest from appium import webdriver from config.config import Config from pages.login_page import LoginPage class TestLogin: @pytest.fixture(scope=‘class’) def driver(self): # 初始化驱动 caps = { … } # 从Config类读取 driver = webdriver.Remote(Config.APPIUM_SERVER, options=caps) yield driver driver.quit() def test_valid_login(self, driver): login_page = LoginPage(driver) login_page.login(‘correct_user’, ‘correct_pwd’) # 添加断言,验证登录成功 assert driver.current_activity == ‘.MainActivity’ -
run_tests.py:可以使用pytest框架来发现并运行所有测试用例,生成报告。
采用这样的结构,当登录页面的输入框ID发生变化时,你只需要修改 login_page.py 文件中的一个常量,所有用到这个输入框的测试用例都会自动生效,维护成本大大降低。这是从小脚本走向可维护自动化项目的关键一步。
更多推荐
所有评论(0)