iOS appium元素定位,封装时候使用MobileBy和By结合

iOS Appium 元素定位与封装技巧
本文主要探讨了在iOS Appium自动化测试中,如何有效地进行元素定位,并结合MobileBy和By进行综合封装,提升测试效率。通过实例说明了在iOS环境下,利用MobileBy的多种定位方式,如 accessibility_id、UIAutomation 等,以及如何与By配合,实现更灵活精准的元素查找。这对于自动化测试脚本的编写和维护具有重要意义。

iOS:

from selenium.webdriver.common.by import By
class MobileBy(By):
    IOS_PREDICATE = '-ios predicate string'
    IOS_UIAUTOMATION = '-ios uiautomation'
    IOS_CLASS_CHAIN = '-ios class chain'
    ANDROID_UIAUTOMATOR = '-android uiautomator'
    ANDROID_VIEWTAG = '-android viewtag'
    ANDROID_DATA_MATCHER = '-android datamatcher'
    ACCESSIBILITY_ID = 'accessibility id'
    IMAGE = '-image'
    CUSTOM = '-custom'

android:

class By(object):
    """
    Set of supported locator strategies.
    """

    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"

综合封装:

def find_element(self, *loc):
    try:
        # 元素可见时,返回查找到的元素;以下入参为元组的元素,需要加*
        WebDriverWait(self.driver, 30).until(lambda driver: driver.find_element(*loc).is_displayed())
        return self.driver.find_element(*loc)

    except selenium.common.exceptions.NoSuchElementException:
        # logging.warning('Can not find element: %s' % loc[1])
        self.log.myloggger('Can not find element: %s' % loc[1], flag=2)
        raise
    except selenium.common.exceptions.TimeoutException:
        self.log.myloggger('Can not find element: %s' % loc[1], flag=2)
        raise

def find_elements(self, *loc):
    try:
        WebDriverWait(self.driver, 30).until(lambda driver: driver.find_elements(*loc))
        return self.driver.find_elements(*loc)

    except selenium.common.exceptions.NoSuchElementException:
        # logging.warning('Can not find element: %s' % loc[1])
        self.log.myloggger('Can not find element: %s' % loc[1], flag=2)
        self.get_screenshot()
        raise
<think>我们正在解决如何定位并移除Appium中的蒙版元素(覆盖层),以便操作下方的元素。蒙版通常是一个半透明的层,会阻止用户与底层元素的交互。常见的场景包括新手引导、广告弹窗、权限请求等。 关键思路: 1. 定位蒙版元素本身(通常是一个全屏或部分屏幕的视图) 2. 通过点击蒙版上的关闭按钮、跳过按钮,或者直接点击蒙版特定区域来关闭它 3. 如果无法关闭,可以尝试其他方法(如等待超时、模拟返回键等) 具体步骤: 步骤1:识别蒙版元素 使用Appium Inspector或UI Automator Viewer等工具查看蒙版元素的属性。常见的定位方式包括: - 通过ID定位(如果有固定资源ID) - 通过类名定位(如:android.view.View, XCUIElementTypeOther 等通用视图) - 通过文本定位(如“跳过”、“我知道了”等) - 通过XPath定位(当蒙版没有明显特征时,可能需要使用XPath来定位其在整个节点树中的位置) 示例代码(定位蒙版上的关闭按钮): ```java // 通过ID定位关闭按钮(推荐) MobileElement closeBtn = driver.findElement(By.id("com.example:id/btn_close")); // 通过文本定位(适用于按钮上有文字) MobileElement skipBtn = driver.findElement(AppiumBy.androidUIAutomator("new UiSelector().text(\"跳过\")")); // 通过XPath定位(当没有ID文本时) MobileElement mask = driver.findElement(By.xpath("//android.view.View[@clickable='true' and @bounds='[0,0][1080,1920]']")); ``` 步骤2:关闭蒙版 定位到关闭按钮或可点击区域后,执行点击操作: ```java closeBtn.click(); ``` 如果没有明显的关闭按钮,但蒙版本身可点击关闭,则可以直接点击蒙版元素: ```java mask.click(); ``` 步骤3:处理无法直接关闭的蒙版 如果蒙版没有关闭按钮且不可点击,可以尝试: - 等待蒙版自动消失(设置显式等待) - 模拟物理返回键(适用于按返回键可关闭的情况) - 使用坐标点点击(不推荐,但作为最后手段) 示例(等待蒙版消失): ```java WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.invisibilityOf(mask)); ``` 示例(模拟返回键): ```java driver.pressKey(new KeyEvent(AndroidKey.BACK)); ``` 步骤4:验证蒙版已关闭 在继续操作前,确保蒙版已关闭。可以通过检查蒙版是否消失,或者底层元素是否可操作来判断: ```java // 等待蒙版消失 wait.until(ExpectedConditions.invisibilityOf(mask)); // 或者等待底层元素出现并可点击 wait.until(ExpectedConditions.elementToBeClickable(By.id("com.example:id/underlying_element"))); ``` 步骤5:定位并操作底层元素 确认蒙版关闭后,即可正常操作底层元素: ```java MobileElement targetElement = driver.findElement(By.id("com.example:id/underlying_element")); targetElement.click(); ``` 特殊情况处理: 1. 多层蒙版:可能需要连续关闭多个蒙版。建议封装一个关闭蒙版的函数,在每次操作前调用。 2. 动态加载的蒙版:在页面切换后可能出现新的蒙版,因此需要在关键步骤后添加蒙版检查。 封装关闭蒙版的函数(伪代码): ```java public void closeMaskIfPresent() { try { // 尝试定位关闭按钮 MobileElement closeBtn = driver.findElement(By.id("com.example:id/btn_close")); closeBtn.click(); } catch (NoSuchElementException e) { // 没有蒙版,继续 } } ``` 注意事项: - 蒙版元素定位可能因应用版本更新而变化,建议使用相对稳定的定位方式(如资源ID)。 - 避免使用绝对坐标点击,因为不同设备分辨率不同。 - 如果蒙版是WebView中的元素,需要先切换到WebView上下文。 引用说明: 定位蒙版元素的方法参考了Appium的常用定位策略[^1],通过关闭按钮的点击来移除蒙版[^2]。处理无法关闭的蒙版时,模拟返回键是一种常见的系统级操作[^3]。 相关问题: 1. Appium中如何定位动态变化的蒙版元素? 2. 如何处理WebView内的蒙版? 3. 在iOSAndroid上处理蒙版有哪些差异? 4. 如何编写健壮性高的蒙版处理函数?</think>### Appium 定位蒙版元素并移除/忽略的方法 蒙版元素(如新手引导、广告弹窗、加载遮罩)会阻挡底层元素的操作。以下是定位并处理蒙版的核心方法: --- ### 一、定位蒙版元素的方法 1. **通过遮罩层特征定位** ```java // 定位全屏半透明蒙版 (Android) MobileElement mask = driver.findElement(By.xpath("//*[contains(@class, 'View') and @clickable='false']")); // iOS定位示例 MobileElement iosMask = driver.findElement(AppiumBy.iOSClassChain("**/XCUIElementTypeOther[`rect.width == ${screenWidth}`]")); ``` 2. **通过关闭按钮定位** ```java // 定位蒙版上的关闭按钮 MobileElement closeBtn = driver.findElement(AppiumBy.accessibilityId("close")); // 或通过文本定位 MobileElement skipBtn = driver.findElement(AppiumBy.androidUIAutomator( "new UiSelector().textContains(\"跳过\")")); ``` 3. **通过坐标定位(最后手段)** ```java // 获取屏幕尺寸 Dimension size = driver.manage().window().getSize(); // 点击右上角关闭区域 (x: 90%宽度, y: 10%高度) new TouchAction(driver).tap(PointOption.point( (int)(size.width * 0.9), (int)(size.height * 0.1) )).perform(); ``` --- ### 二、移除/忽略蒙版的策略 #### 方法1:主动关闭蒙版 ```java // 定位并点击关闭按钮 try { MobileElement closeBtn = driver.findElement(By.id("com.app:id/btn_close")); closeBtn.click(); // 等待蒙版消失 new WebDriverWait(driver, Duration.ofSeconds(5)) .until(ExpectedConditions.invisibilityOf(closeBtn)); } catch (NoSuchElementException e) { // 无蒙版时跳过 } ``` #### 方法2:绕过蒙版定位底层元素 ```java // 通过坐标直接点击底层元素 (需计算元素中心点) MobileElement target = driver.findElement(By.id("target_element")); Point center = target.getCenter(); new TouchAction(driver).tap(PointOption.point(center)).perform(); ``` #### 方法3:强制穿透蒙版(Android专属) ```java // 使用UIAutomator的forceClick属性 String script = "mobile: clickGesture"; Map<String, Object> params = new HashMap<>(); params.put("elementId", ((RemoteWebElement)target).getId()); params.put("force", true); // 关键参数:强制穿透点击 driver.executeScript(script, params); ``` #### 方法4:禁用蒙版(开发环境) ```java // 通过ADB命令关闭应用蒙版 (需root) driver.executeScript("mobile: shell", ImmutableMap.of( "command", "pm disable com.app.package/com.app.MaskActivity" )); ``` --- ### 三、处理动态蒙版的最佳实践 1. **封装蒙版检测函数** ```java public void handleMask() { List<MobileElement> masks = driver.findElements(By.xpath("//*[contains(@text, '跳过')]")); if(!masks.isEmpty()) masks.get(0).click(); } // 在关键操作前调用 handleMask(); driver.findElement(By.id("main_button")).click(); ``` 2. **结合等待策略** ```java // 等待蒙版出现后再关闭 new WebDriverWait(driver, Duration.ofSeconds(10)) .ignoring(NoSuchElementException.class) .until(d -> { d.findElement(By.id("mask")).click(); return true; }); ``` 3. **多平台兼容处理** ```java if (driver.getCapabilities().getPlatformName().equals(Platform.ANDROID)) { // Android处理逻辑 } else { // iOS处理逻辑 driver.findElement(AppiumBy.iOSNsPredicateString("label == '继续'")).click(); } ``` --- ### 关键注意事项 1. **优先级顺序**:优先尝试关闭按钮 > 坐标点击 > 强制穿透 2. **设备适配**:坐标点击需结合屏幕比例计算,使用相对坐标而非绝对坐标 3. **性能影响**:强制穿透(`force=true`)可能破坏页面逻辑,仅作为最后手段[^1] 4. **工具辅助**:使用Appium Inspector的**元素快照**功能分析蒙版层级结构[^4] > 通过组合主动关闭强制穿透策略,可处理95%的蒙版场景。对于无法关闭的系统级蒙版(如权限弹窗),需使用`driver.switchTo().alert()`处理[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值