appium从入门到精通php,移动端自动化测试Appium 从入门到项目实战Python版

appium从入门到精通php,移动端自动化测试Appium 从入门到项目实战Python版---youkeit.xyz/13549/

Appium+Python自动化测试:元素定位与疑难问题解决方案

一、Appium环境搭建

1.1 基础环境配置

组件 版本要求 安装方式
Python 3.7+ 官网下载
Appium Server 1.22+ npm install -g appium
Appium Client 2.0+ pip install Appium-Python-Client
Android SDK API 24+ Android Studio
Java JDK 8+ Oracle官网

1.2 环境验证代码

python 复制代码
from appium import webdriver

def test_environment():
    caps = {
        "platformName": "Android",
        "deviceName": "emulator-5554",
        "appPackage": "com.android.settings",
        "appActivity": ".Settings"
    }
    
    driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    print("连接Appium Server成功!")
    driver.quit()

if __name__ == '__main__':
    test_environment()

二、元素定位核心方法

2.1 八大定位策略对比

定位方式 示例代码 适用场景 执行效率
ID定位 find_element(By.ID, "com.example:id/btn") 有唯一resource-id时 ★★★★★
XPath find_element(By.XPATH, "//android.widget.Button[@text='登录']") 复杂层级结构 ★★☆☆☆
Accessibility ID find_element(By.ACCESSIBILITY_ID, "登录按钮") 有content-desc时 ★★★★☆
Class Name find_element(By.CLASS_NAME, "android.widget.Button") 同类元素批量操作 ★★★☆☆
UIAutomator find_element(By.ANDROID_UIAUTOMATOR, 'text("登录")') Android专属定位 ★★★☆☆
CSS Selector find_element(By.CSS_SELECTOR, "Button.login-btn") WebView混合应用 ★★☆☆☆
文本定位 find_element(By.XPATH, "//*[@text='登录']") 有明确文本内容 ★★★☆☆
组合定位 find_element(By.XPATH, "//android.widget.EditText[@resource-id='username']") 提高定位准确性 ★★★☆☆

2.2 定位工具使用技巧

使用uiautomatorviewer

  1. 进入Android SDK的tools/bin目录
  2. 执行./uiautomatorviewer
  3. 点击设备截图按钮
  4. 查看元素属性

Appium Inspector

bash 复制代码
appium inspector --session-override

在可视化界面操作APP并生成定位代码

三、XPath高级定位技巧

3.1 常用XPath表达式

python 复制代码
# 绝对路径定位
driver.find_element(By.XPATH, "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.Button")

# 相对路径+属性组合
driver.find_element(By.XPATH, "//android.widget.EditText[@resource-id='username']")

# 文本匹配
driver.find_element(By.XPATH, "//*[contains(@text, '登录')]")

# 多条件筛选
driver.find_element(By.XPATH, "//android.widget.Button[@enabled='true' and @text='提交']")

# 层级关系定位
driver.find_element(By.XPATH, "//android.widget.ScrollView/android.widget.LinearLayout[2]/android.widget.RadioButton[1]")

3.2 XPath性能优化

  1. 避免使用//开头:改为相对路径
  2. 减少层级 :如//*[@resource-id='container']//Button优于/a/b/c/d/Button
  3. 优先使用索引LinearLayout[1]比复杂的属性选择更快
  4. 使用contains模糊匹配:应对动态文本

四、元素定位疑难问题解决

4.1 常见问题排查表

问题现象 可能原因 解决方案
NoSuchElementException 元素未加载/定位表达式错误 1. 添加等待 2. 检查表达式
StaleElementReferenceException DOM结构已变化 重新获取元素引用
ElementNotInteractableException 元素不可交互 1. 检查可见性 2. 坐标点击
InvalidSelectorException 非法定位表达式 检查XPath/CSS语法
TimeoutException 元素加载超时 调整等待时间/优化网络

4.2 智能等待策略

python 复制代码
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 显式等待元素出现
element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "com.example:id/btn"))
)

# 自定义等待条件
def is_element_enabled(locator):
    def _predicate(driver):
        try:
            return driver.find_element(*locator).is_enabled()
        except:
            return False
    return _predicate

WebDriverWait(driver, 15).until(
    is_element_enabled((By.XPATH, "//Button[@text='下一步']"))
)

4.3 动态元素处理

python 复制代码
# 处理动态ID
driver.find_element(By.XPATH, "//*[starts-with(@resource-id, 'com.example:id/dynamic_')]")

# 处理动态文本
driver.find_element(By.XPATH, "//*[contains(@text, '验证码')]")

# 使用正则匹配(UIAutomator2)
driver.find_element(By.ANDROID_UIAUTOMATOR, 
    'new UiSelector().textMatches(".*剩余.*")')

五、实战案例:登录页面自动化

5.1 元素定位封装

python 复制代码
class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        
    @property
    def username_field(self):
        return self.driver.find_element(By.ID, "com.example:id/et_username")
    
    @property
    def password_field(self):
        return self.driver.find_element(By.XPATH, "//android.widget.EditText[contains(@text,'密码')]")
    
    @property
    def login_button(self):
        return WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.ACCESSIBILITY_ID, "登录按钮"))
        )
    
    def login(self, username, password):
        self.username_field.clear()
        self.username_field.send_keys(username)
        self.password_field.send_keys(password)
        self.login_button.click()

5.2 异常处理流程

python 复制代码
def safe_login(driver, username, password, retries=3):
    for attempt in range(retries):
        try:
            LoginPage(driver).login(username, password)
            return True
        except Exception as e:
            print(f"登录失败,尝试 {attempt + 1}/{retries}: {str(e)}")
            if attempt == retries - 1:
                raise
            # 失败后操作
            driver.back()
            time.sleep(2)
    return False

六、混合应用与H5元素定位

6.1 上下文切换

python 复制代码
# 获取所有上下文
contexts = driver.contexts
print("可用上下文:", contexts)

# 切换到WEBVIEW
driver.switch_to.context('WEBVIEW_com.example.app')

# 定位H5元素
driver.find_element(By.CSS_SELECTOR, ".login-form input[name='username']")

# 切换回NATIVE
driver.switch_to.context('NATIVE_APP')

6.2 Chrome DevTools协议

python 复制代码
# 启用Chrome调试
caps = {
    "chromedriverExecutable": "/path/to/chromedriver",
    "chromedriverChromeMappingFile": "/path/to/mapping.json"
}

# 执行JavaScript
driver.execute_script("document.querySelector('.btn-submit').click();")

七、性能优化与最佳实践

7.1 定位优化技巧

  1. 缓存元素引用:频繁操作的元素只定位一次

    python 复制代码
    login_btn = driver.find_element(By.ID, "login_btn")
    login_btn.click()
    login_btn.get_attribute("enabled")
  2. 缩小定位范围

    python 复制代码
    parent = driver.find_element(By.ID, "form_container")
    parent.find_element(By.CLASS_NAME, "input-field")
  3. 优先使用原生定位:Android用UIAutomator,iOS用XCUITest

7.2 测试框架集成

python 复制代码
import unittest
import pytest
from appium import webdriver

class TestLogin(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        caps = {...}
        cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    
    def test_valid_login(self):
        LoginPage(self.driver).login("user", "pass")
        self.assertTrue(HomePage(self.driver).is_displayed())
    
    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

if __name__ == '__main__':
    pytest.main(["-v", "test_login.py"])

附录:实用资源与工具

元素定位辅助工具

工具名称 平台 特点
Appium Inspector 跨平台 官方可视化工具
UI Automator Viewer Android SDK内置,无需额外安装
Xcode Accessibility Inspector iOS Apple官方工具
Flipper 跨平台 Facebook开发,支持插件扩展

常用XPath函数

函数 示例 说明
contains() //*[contains(@text, '价')] 文本包含
starts-with() //*[starts-with(@id, 'btn_')] 属性值开头匹配
text() //*[text()='登录'] 精确文本匹配
last() (//Button)[last()] 选择最后一个元素
position() //Button[position()<3] 按位置选择

通过本指南,您将掌握:

  1. Appium+Python环境搭建与验证
  2. 8种元素定位策略的适用场景
  3. XPath高级定位技巧与性能优化
  4. 常见定位问题的解决方案
  5. 混合应用与H5元素处理方法

建议按照以下步骤实践:

  1. 使用uiautomatorviewer分析APP元素
  2. 编写简单定位脚本验证基础元素
  3. 实现完整页面对象模型
  4. 添加异常处理与日志记录
  5. 集成到持续测试流水线

遇到问题时优先检查:

  1. 元素是否在正确的上下文中
  2. 是否添加了足够的等待时间
  3. 定位表达式是否唯一匹配
  4. 应用是否处于预期页面状态
相关推荐
天天摸鱼的java工程师3 小时前
SpringCloud + Nacos + Feign + Resilience4j:微服务间调用的熔断降级与重试策略
后端
长安城没有风3 小时前
从入门到精通【Redis】初识Redis哨兵机制(Sentinel)
java·数据库·redis·后端
canonical_entropy3 小时前
范式重构:可逆计算如何颠覆DDD的经典模式
后端·低代码·领域驱动设计
绝无仅有3 小时前
某大厂跳动Java面试真题之问题与解答总结(五)
后端·面试·github
我是天龙_绍3 小时前
SpringBoot如何整合Mybatis-Plus
后端
绝无仅有3 小时前
某大厂跳动Java面试真题之问题与解答总结(四)
后端·面试·github
昵称为空C4 小时前
Jmeter 性能测试利器-1(入门指南)
后端·测试
景同学4 小时前
Dify离线安装沙箱服务的Python依赖包
后端
cr7xin4 小时前
go语言结构体内存对齐
后端·golang