下面是一个完整的 Appium WebDriver 支持的常用方法汇总,并附上典型用法示例。
find_element()
和 find_elements()
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
# 单个元素查找
el = driver.find_element(by=AppiumBy.ID, value="com.example:id/username")
# 多个元素查找
els = driver.find_elements(by=AppiumBy.CLASS_NAME, value="android.widget.EditText")
AppiumBy
):定位方式 | 示例值 |
---|---|
AppiumBy.ID |
"com.example:id/btn_login" |
AppiumBy.CLASS_NAME |
"android.widget.EditText" |
AppiumBy.NAME |
"login_button" (已不推荐) |
AppiumBy.XPATH |
"//android.widget.TextView[@text='Submit']" |
AppiumBy.ACCESSIBILITY_ID |
"button_login" |
AppiumBy.ANDROID_UIAUTOMATOR |
'new UiSelector().resourceId("com.example:id/login")' |
AppiumBy.IOS_PREDICATE |
"label == 'Login'" (iOS 专用) |
AppiumBy.IOS_CLASS_CHAIN |
"XCUIElementTypeButton[1]" (iOS 专用) |
举例说明常用的 Appium 定位方式(配合 Appium Inspector 使用)
我们以一个假设的登录页面为例,其中包含以下 UI 元素信息(通过 Appium Inspector 查看):
属性 | 值 |
---|---|
用户名输入框 | resource-id="com.example:id/username" |
密码输入框 | class="android.widget.EditText" |
登录按钮 | text="Login" 或 content-desc="login_button" |
发送按钮 | resource-id="com.example:id/send" |
提交按钮 | xpath="//android.widget.Button[@text='Submit']" |
ID
定位(推荐)from appium.webdriver.common.appiumby import AppiumBy
# 定位发送按钮
send_button = driver.find_element(by=AppiumBy.ID, value="com.example:id/send")
send_button.click()
XPath
定位(灵活但效率略低)submit_button = driver.find_element(
by=AppiumBy.XPATH,
value="//android.widget.Button[@text='Submit']"
)
submit_button.click()
Class Name
定位(适用于多个同类型元素)edit_text_list = driver.find_elements(
by=AppiumBy.CLASS_NAME,
value="android.widget.EditText"
)
# 输入用户名到第一个 EditText
edit_text_list[0].send_keys("testuser")
Accessibility ID
(content-desc)定位login_button = driver.find_element(
by=AppiumBy.ACCESSIBILITY_ID,
value="login_button"
)
login_button.click()
Text
定位(注意大小写和空格)login_button = driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().text("Login")'
)
login_button.click()
button = driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().textContains("Sub")'
)
button.click()
resource-id
+ text
组合定位(更稳定)element = driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().resourceId("com.example:id/send").text("Send Message")'
)
element.click()
new UiSelector()语法定位元素
在 Appium 自动化测试中,特别是在 Android 平台上,new UiSelector()
是一种非常强大且灵活的定位元素方式。它属于 Android UI Automator 提供的 API,允许你通过多种属性组合来精确定位页面上的控件。
new UiSelector()
UiSelector
是 Android UI Automator 提供的一个类。AppiumBy.ANDROID_UIAUTOMATOR
来使用它。text
, resourceId
, className
, index
, description
等)进行查找,适合处理复杂的 UI 结构。from appium.webdriver.common.appiumby import AppiumBy
element = driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().()'
)
⚠️ 注意:传入的是一个字符串表达式,语法要严格符合 Java 的写法。
text(String text)
根据文本内容定位控件。
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().text("Login")'
)
适用于按钮、TextView 等显示文字的控件。
textContains(String substr)
模糊匹配文本内容(包含子串)
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().textContains("Log")'
)
textStartsWith(String prefix)
以某个前缀开头的文本
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().textStartsWith("Wel")'
)
textMatches(Pattern regex)
正则匹配文本内容
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().textMatches("^User\\d+$")' # 匹配 "User123"
)
resourceId(String id)
通过资源 ID 定位控件(推荐用 AppiumBy.ID
更简洁)
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().resourceId("com.example:id/username")'
)
className(String className)
通过类名定位控件(如 EditText
, Button
)
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().className("android.widget.Button")'
)
description(String contentDescription)
通过 content-desc
属性定位(Accessibility ID)
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().description("menu_icon")'
)
index(int index)
通过索引定位(慎用,容易变化)
# 找第一个 TextView
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().className("android.widget.TextView").index(0)'
)
instance(int instance)
获取某一类控件中的第几个实例(类似 XPath 中的 [n])
# 获取第二个 EditText
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().className("android.widget.EditText").instance(1)'
)
你可以组合多个条件来更精确地定位元素:
# 同时匹配 resourceId 和 text
driver.find_element(
by=AppiumBy.ANDROID_UIAUTOMATOR,
value='new UiSelector().resourceId("com.example:id/login").text("Login")'
)
项目 | 说明 |
---|---|
性能 | 比 ID 和 XPath 略慢,但比 XPath 更稳定 |
推荐用途 | 复杂控件、动态内容、没有唯一 ID 的场景 |
调试建议 | 使用 Appium Inspector 查看控件属性 |
只能在 Android 上使用 | 不支持 iOS,iOS 需要用 IosUIAutomation 或 Predicate String |
❓ Q1:为什么找不到元素?
time.sleep()
或显式等待;driver.page_source
查看当前页面结构。定位方式 | 示例值 | 特点 |
---|---|---|
AppiumBy.ID |
"com.example:id/send" |
推荐使用,速度快,唯一性强 |
AppiumBy.XPATH |
"//android.widget.Button[@text='Submit']" |
灵活但慢,适合结构化定位 |
AppiumBy.CLASS_NAME |
"android.widget.EditText" |
多个元素时需结合索引 |
AppiumBy.ACCESSIBILITY_ID |
"login_button" |
依赖无障碍描述,iOS 和 Android 都支持 |
AppiumBy.ANDROID_UIAUTOMATOR |
'new UiSelector().text("Login")' |
Android 专属,强大但语法复杂 |
在使用 Appium 定位到元素之后,除了 click()
动作之外,还有许多其他动作可以对这些元素执行。以下是几种常见的操作方法:
send_keys()
:向输入框中输入文本。 element = driver.find_element(by=AppiumBy.ID, value="com.example:id/username")
element.send_keys("testuser")
clear()
:清除输入框中的现有文本。 element = driver.find_element(by=AppiumBy.ID, value="com.example:id/username")
element.clear()
text
属性:获取元素显示的文本内容。 element = driver.find_element(by=AppiumBy.ID, value="com.example:id/message")
print(element.text)
is_displayed()
:判断元素是否对用户可见。is_enabled()
:检查元素是否可用(例如按钮是否可点击)。 element = driver.find_element(by=AppiumBy.ID, value="com.example:id/loginButton")
if element.is_displayed() and element.is_enabled():
element.click()
get_attribute(name)
:获取元素的特定属性值。 element = driver.find_element(by=AppiumBy.ID, value="com.example:id/username")
attribute_value = element.get_attribute("name") # 或者 "content-desc", "resource-id" 等
submit()
:对于某些支持提交的元素(如表单),可以调用此方法来提交。 form_element = driver.find_element(by=AppiumBy.ID, value="com.example:id/loginForm")
form_element.submit()
虽然不是直接作用于元素的方法,但你可以通过 TouchAction
类对特定元素执行触摸手势:
from appium.webdriver.common.touch_action import TouchAction
action = TouchAction(driver)
action.long_press(el=element).wait(1000).release().perform()
有时候你可能需要等待某个元素变为可见或者存在:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.visibility_of_element_located((AppiumBy.ID, "com.example:id/username")))
size
属性 和 location
属性:分别用于获取元素的尺寸和屏幕上的位置。 element = driver.find_element(by=AppiumBy.ID, value="com.example:id/username")
print("Size:", element.size)
print("Location:", element.location)
尽管不是直接针对元素的方法,但你可以截取整个屏幕的截图,然后根据需要裁剪出特定元素的部分:
driver.save_screenshot('screenshot.png')
:保存当前屏幕截图。MobileCommand
)这些方法只能在 Appium 中使用,Selenium 不支持。
driver.swipe(start_x=100, start_y=800, end_x=100, end_y=200, duration=800)
driver.drag_and_drop(origin_el, destination_el)
from appium.webdriver.common.touch_action import TouchAction
action = TouchAction(driver)
action.press(x=100, y=500).wait(1000).release().perform()
更推荐使用新版的
W3CActions
方式。
driver.activate_app('com.example.app') # 启动应用
driver.background_app(5) # 将应用置于后台运行5秒
driver.terminate_app('com.example.app') # 强制停止应用
print("Current Package:", driver.current_package)
print("Current Activity:", driver.current_activity)
driver.install_app('/path/to/app.apk')
driver.remove_app('com.example.app')
if driver.is_app_installed('com.example.app'):
print("App is installed.")
contexts = driver.contexts
print("Available contexts:", contexts)
driver.switch_to.context(contexts[-1]) # 切换到 WebView
print("Device time:", driver.device_time)
driver.press_keycode(4) # 返回键 KEYCODE_BACK
driver.save_screenshot('screen.png')
如果你是在 WebView 中进行操作,可以使用类似 Selenium 的方式:
driver.get("https://example.com")
print("Current URL:", driver.current_url)
driver.back()
driver.forward()
el.send_keys("Hello World")
el.clear()
如果遇到中文输入问题,可设置以下 Desired Capabilities:
'dict': {
'resetKeyboard': True,
'unicodeKeyboard': True
}
driver.save_screenshot('test.png') # 保存截图
driver.get_screenshot_as_base64() # 获取 base64 编码图片
driver.is_locked() # 是否锁屏
driver.unlock() # 解锁
driver.lock(5) # 锁屏5秒后自动解锁
driver.set_network_connection(6) # 设置网络连接类型
result = driver.execute_script("mobile: scroll", {"direction": "down"})
你也可以直接调用底层命令:
driver.execute("mobile: longClickGesture", {
"x": 100,
"y": 100,
"duration": 1000
})
driver.quit() # 结束当前会话
driver.close_app() # 关闭当前应用但不结束会话
logs = driver.get_log('logcat')
for log in logs:
print(log)
支持的日志类型包括:
logcat
bugreport
server
driver
client
你可以通过以下方式查看所有可用的方法:
dir(driver)
或者访问官方文档:
Appium-Python-Client 文档
功能 | 方法 |
---|---|
查找元素 | find_element , find_elements |
触摸操作 | swipe , drag_and_drop , press_keycode |
应用控制 | activate_app , terminate_app , background_app |
安装卸载 | install_app , remove_app , is_app_installed |
上下文切换 | switch_to.context() |
输入文本 | send_keys , clear |
截图 | save_screenshot , get_screenshot_as_base64 |
执行脚本 | execute_script , execute |
日志获取 | get_log('logcat') |
锁屏操作 | is_locked , unlock , lock |
如果你有具体需求或想了解某个功能的详细用法,欢迎告诉我,我可以为你提供代码示例!