python+appuim实现APP自动化教程
本教程详细介绍了使用Python+Appium实现APP自动化的完整流程。主要内容包括:环境搭建(Python、Appium、Android/iOS工具安装)、基础脚本编写、核心概念(DesiredCapabilities配置、8种元素定位方法)、常用操作(点击、输入、滑动等)、高级功能(页面滑动、源码获取、截图)以及实用工具类实现。教程还提供了测试框架集成示例(Pytest)、微信发消息实战案例
·
Python + Appium 实现 APP 自动化教程
一、环境搭建
1.1 安装必要软件
# 1. 安装 Python(建议 3.8+)
# 下载地址:https://www.python.org/downloads/
# 2. 安装 Appium
# 方法一:通过 npm 安装
npm install -g appium
# 方法二:安装 Appium Desktop
# 下载地址:https://github.com/appium/appium-desktop/releases
# 3. 安装 Appium Python 客户端
pip install Appium-Python-Client
pip install selenium
1.2 安装移动端开发工具
-
Android:安装 Android Studio 和 SDK
-
iOS:安装 Xcode(仅 macOS)
1.3 配置环境变量
# Android 环境变量示例(Windows)
ANDROID_HOME = C:\Users\用户名\AppData\Local\Android\Sdk
# 添加 Path
%ANDROID_HOME%\tools
%ANDROID_HOME%\platform-tools
二、基础示例
2.1 第一个自动化脚本
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import time
# 配置 Desired Capabilities
desired_caps = {
'platformName': 'Android', # 平台
'platformVersion': '11.0', # 系统版本
'deviceName': 'Android Emulator', # 设备名
'appPackage': 'com.android.calculator2', # 应用包名
'appActivity': 'com.android.calculator2.Calculator', # 启动 Activity
'automationName': 'UiAutomator2',
'noReset': True # 不重置应用状态
}
# 连接 Appium 服务器
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
try:
# 点击数字 5
driver.find_element(AppiumBy.ID, 'com.android.calculator2:id/digit_5').click()
# 点击加号
driver.find_element(AppiumBy.ID, 'com.android.calculator2:id/op_add').click()
# 点击数字 3
driver.find_element(AppiumBy.ID, 'com.android.calculator2:id/digit_3').click()
# 点击等号
driver.find_element(AppiumBy.ID, 'com.android.calculator2:id/eq').click()
# 获取结果
result = driver.find_element(AppiumBy.ID, 'com.android.calculator2:id/result').text
print(f'计算结果: {result}')
time.sleep(2)
finally:
driver.quit()
三、核心概念
3.1 Desired Capabilities 配置
# 常用配置项
caps = {
# 基础配置
'platformName': 'Android', # iOS
'platformVersion': '11.0',
'deviceName': '设备名称',
# Android 专用
'appPackage': 'com.example.app',
'appActivity': '.MainActivity',
'automationName': 'UiAutomator2',
'udid': '设备序列号',
# iOS 专用
'bundleId': 'com.example.app',
'automationName': 'XCUITest',
'xcodeOrgId': '团队ID',
'xcodeSigningId': 'iPhone Developer',
# 通用配置
'noReset': True, # 不重置应用
'fullReset': False, # 完全重置
'unicodeKeyboard': True, # 支持 Unicode
'resetKeyboard': True, # 重置键盘
'newCommandTimeout': 60, # 命令超时时间
}
3.2 元素定位方法
# 8 种定位方式
from appium.webdriver.common.appiumby import AppiumBy
# 1. ID 定位
element = driver.find_element(AppiumBy.ID, '元素id')
# 2. 可访问性 ID(content-desc)
element = driver.find_element(AppiumBy.ACCESSIBILITY_ID, '描述')
# 3. Class Name
element = driver.find_element(AppiumBy.CLASS_NAME, '类名')
# 4. XPath
element = driver.find_element(AppiumBy.XPATH, '//元素[@属性="值"]')
# 5. Android UIAutomator
element = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,
'new UiSelector().text("文本")')
# 6. iOS 谓词字符串
element = driver.find_element(AppiumBy.IOS_PREDICATE,
'label == "按钮"')
# 7. iOS Class Chain
element = driver.find_element(AppiumBy.IOS_CLASS_CHAIN,
'**/XCUIElementTypeButton[`label == "按钮"`]')
# 8. 文本定位
element = driver.find_element(AppiumBy.XPATH, '//*[@text="文本内容"]')
四、常用操作
4.1 基本操作
from appium.webdriver.common.touch_action import TouchAction
# 点击操作
element.click()
driver.tap([(x, y)]) # 坐标点击
# 输入文本
element.send_keys('文本内容')
element.clear() # 清空
# 获取元素属性
text = element.text
location = element.location
size = element.size
is_displayed = element.is_displayed()
is_enabled = element.is_enabled()
# 滑动操作
driver.swipe(start_x, start_y, end_x, end_y, duration=800)
# 复杂手势
action = TouchAction(driver)
action.tap(element).perform() # 点击
action.long_press(element, duration=2000).release().perform() # 长按
action.press(x=100, y=100).move_to(x=200, y=200).release().perform() # 拖拽
4.2 等待机制
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 显式等待
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((AppiumBy.ID, '元素id')))
# 隐式等待
driver.implicitly_wait(10) # 全局等待
# 常用条件
EC.visibility_of_element_located(locator) # 元素可见
EC.element_to_be_clickable(locator) # 元素可点击
EC.text_to_be_present_in_element(locator, '文本') # 包含文本
五、高级功能
5.1 页面滑动
def swipe_up(driver, duration=1000):
"""向上滑动"""
size = driver.get_window_size()
start_x = size['width'] * 0.5
start_y = size['height'] * 0.8
end_y = size['height'] * 0.2
driver.swipe(start_x, start_y, start_x, end_y, duration)
def swipe_down(driver, duration=1000):
"""向下滑动"""
size = driver.get_window_size()
start_x = size['width'] * 0.5
start_y = size['height'] * 0.2
end_y = size['height'] * 0.8
driver.swipe(start_x, start_y, start_x, end_y, duration)
# 使用示例
swipe_up(driver) # 上滑
swipe_down(driver) # 下滑
5.2 获取页面源码
# 获取当前页面 XML
page_source = driver.page_source
# 保存到本地
with open('page.xml', 'w', encoding='utf-8') as f:
f.write(page_source)
5.3 截图
# 截图
driver.save_screenshot('screenshot.png')
# 元素截图
element.screenshot('element.png')
六、实用工具类
6.1 基础框架
import yaml
import logging
from datetime import datetime
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class AppAutomation:
def __init__(self, caps=None, config_file='config.yaml'):
"""初始化驱动"""
self.load_config(config_file)
if caps:
self.caps.update(caps)
self.driver = webdriver.Remote(
f"http://{self.config['appium_server']['host']}:"
f"{self.config['appium_server']['port']}/wd/hub",
self.caps
)
self.wait = WebDriverWait(self.driver, 10)
def load_config(self, config_file):
"""加载配置文件"""
with open(config_file, 'r', encoding='utf-8') as f:
self.config = yaml.safe_load(f)
self.caps = self.config.get('desired_capabilities', {})
def find_element(self, by, value, timeout=10):
"""查找元素(带等待)"""
return WebDriverWait(self.driver, timeout).until(
EC.presence_of_element_located((by, value))
)
def find_and_click(self, by, value, timeout=10):
"""查找并点击元素"""
element = self.find_element(by, value, timeout)
element.click()
return element
def find_and_input(self, by, value, text, timeout=10):
"""查找并输入文本"""
element = self.find_element(by, value, timeout)
element.clear()
element.send_keys(text)
return element
def swipe_to_find(self, by, value, max_swipes=5):
"""滑动查找元素"""
for _ in range(max_swipes):
try:
return self.driver.find_element(by, value)
except:
self.swipe_up()
raise Exception(f"未找到元素: {value}")
def take_screenshot(self, name=None):
"""截图"""
if not name:
name = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f"screenshots/{name}.png"
self.driver.save_screenshot(filename)
logging.info(f"截图已保存: {filename}")
return filename
def quit(self):
"""退出"""
if self.driver:
self.driver.quit()
6.2 配置文件示例 (config.yaml)
appium_server:
host: 127.0.0.1
port: 4723
desired_capabilities:
platformName: Android
platformVersion: "11.0"
deviceName: Android Emulator
automationName: UiAutomator2
noReset: true
newCommandTimeout: 60
apps:
calculator:
appPackage: com.android.calculator2
appActivity: com.android.calculator2.Calculator
settings:
appPackage: com.android.settings
appActivity: .Settings
七、测试框架集成
7.1 使用 Pytest
# test_calculator.py
import pytest
from app_automation import AppAutomation
class TestCalculator:
@pytest.fixture(scope='class')
def app(self):
"""初始化应用"""
app = AppAutomation()
yield app
app.quit()
def test_addition(self, app):
"""测试加法"""
# 执行加法
app.find_and_click(AppiumBy.ID, 'digit_5')
app.find_and_click(AppiumBy.ID, 'op_add')
app.find_and_click(AppiumBy.ID, 'digit_3')
app.find_and_click(AppiumBy.ID, 'eq')
# 验证结果
result = app.find_element(AppiumBy.ID, 'result').text
assert result == '8'
def test_clear(self, app):
"""测试清除功能"""
app.find_and_click(AppiumBy.ID, 'digit_9')
app.find_and_click(AppiumBy.ID, 'clr')
result = app.find_element(AppiumBy.ID, 'result').text
assert result == '0'
# 运行测试
# pytest test_calculator.py -v
7.2 生成测试报告
# 安装 pytest-html
pip install pytest-html
# 运行测试并生成报告
pytest test_calculator.py --html=report.html --self-contained-html
八、实战案例
8.1 微信发消息自动化
class WeChatAutomation(AppAutomation):
def __init__(self):
caps = {
'appPackage': 'com.tencent.mm',
'appActivity': '.ui.LauncherUI',
'noReset': True
}
super().__init__(caps)
def send_message(self, contact_name, message):
"""发送微信消息"""
# 搜索联系人
self.find_and_click(AppiumBy.ID, '搜索按钮ID')
self.find_and_input(AppiumBy.ID, '搜索框ID', contact_name)
# 进入聊天
self.find_and_click(AppiumBy.XPATH, f'//*[@text="{contact_name}"]')
# 输入消息
input_box = self.find_element(AppiumBy.ID, '输入框ID')
input_box.send_keys(message)
# 发送
self.find_and_click(AppiumBy.ID, '发送按钮ID')
# 验证发送成功
last_msg = self.find_element(
AppiumBy.XPATH, '(//消息元素)[last()]'
).text
assert message in last_msg
九、调试技巧
9.1 使用 UI Automator Viewer
# Android SDK 工具
# 位置: {ANDROID_HOME}/tools/bin/uiautomatorviewer
9.2 使用 Appium Inspector
-
启动 Appium Server
-
打开 Appium Inspector
-
配置 Desired Capabilities
-
连接设备/模拟器
-
实时查看和操作元素
9.3 日志记录
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('appium.log'),
logging.StreamHandler()
]
)
十、常见问题
10.1 连接问题
# 检查 Appium 服务
# 终端执行:
appium --address 127.0.0.1 --port 4723
# 检查设备连接
adb devices
10.2 元素定位失败
-
使用
driver.page_source查看当前页面结构 -
增加等待时间
-
使用相对定位代替绝对定位
-
尝试不同的定位方式
10.3 性能优化
# 1. 减少不必要的截图
# 2. 使用合适的等待策略
# 3. 复用 driver 会话
# 4. 批量执行操作
学习资源
-
官方文档
-
Appium 官方文档:http://appium.io/docs/en/about-appium/intro/
-
Appium Python 客户端:https://github.com/appium/python-client
-
-
实用工具
-
Appium Desktop:图形化工具
-
ADB:Android 调试桥
-
Charles/Fiddler:网络抓包
-
-
社区支持
-
GitHub Issues
-
Stack Overflow
-
官方讨论区
-
这个教程涵盖了 Python + Appium 进行 APP 自动化的主要方面。建议从基础示例开始,逐步尝试更复杂的功能。实践中遇到问题,多查阅官方文档和社区讨论。
更多推荐
所有评论(0)