解决App自动化的不稳定因素-弹框及首页启动加载完成判断处理

本文详述了App自动化测试中遇到的弹框问题及其处理策略,包括使用黑名单List、trycatch、PageSource和首页判断等方法,有效提升自动化测试的稳定性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、“罪恶”源泉

经常我们会觉得App自动化不靠谱,不稳定,其中很大的两个原因是:

  • App启动加载时间较久(可能App本身加载慢,可能移动设备本身加载应用速度慢,也可能首页广告时间较长)。
  • 各种弹框的出现;广告弹框,升级弹框,评价弹框等。

例如如下雪球App出现的几种弹框:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在框架中若不对上述情况做处理就可能出现元素定位超时找不到的报错,自动化也就被打断终止了,使我们刚燃起的自动化热情瞬间被扑灭,从入门到完全放弃就这样造成了。

2、弹框处理

2.1 处理方向
  • 弹框的影响范围
    弹框对我们自动化的影响主要是用例执行的打断,而至于弹框中广告内容的跳转或评价信息填写等属于另外的测试,因此我们主要是要将弹框处理消失,使应用回到用例执行的PO;
  • 弹框的消失方式
    观察弹框,我们会发现一般为了保证用户体验,弹框都会方便用户进行一键消除,例如上述中雪球的各种弹框,可能点击一个叉号,可能任意点击其他地方,或者评价框这种直接点击“下次再说”等。
  • 弹框的处理效果
    自动化执行的任何时候,任意的弹框都可能出现,在这个时候用例不能失败,需要将对应的弹框正确处理后继续执行原用例,原用例的执行过程不受影响。
2.2 处理思路与实操
2.2.1 循环判断
  1. 将需要处理的弹框元素加入到一个黑名单List中,遍历List,通过findElements方法得到的List大小来判断弹框元素是否存在,存在即点击处理
    public static void handleAlert(){
            List<By> alertBox = new ArrayList<>();
            alertBox.add(By.id("ib_close"));   //广告弹框
            alertBox.add(By.id("md_buttonDefaultNegative")); //评价弹框
    
            alertBox.forEach(alert->{
                By adsLocator = alert;
                List<WebElement> ads = driver.findElements(adsLocator);
                if (ads.size() >= 1) {
                    ads.get(0).click();
                }
            });
        }
    
  2. handleAlert()方法加到driver.findElement方法之前,使定位前先判断弹框的存在与否并进行处理
    public static WebElement findElement(By by) {
                System.out.println(by);
                handleAlert();
                return driver.findElement(by);
                }
    
    上述方法初步解决了弹框问题,但是缺点也很明显:
    缺点:每次定位元素前都需要处理弹框,影响执行效率,速度较慢
    因此我们引入try catch来解决此问题
2.2.2 try catch提升效率
  • 我们利用try catch的异常捕获处理的机制,让元素仅在定位失败时才进入弹框处理handleAlert()方法,处理完毕后重新返回driver.findElement(by),对原case元素继续进行定位执行;这样就大大提升了处理效率,使处理更为精准
    public static WebElement findElement(By by) {
            try {
                System.out.println(by);
                return driver.findElement(by);
            } catch (Exception e) {
                System.out.println("进入弹框处理");
                handleAlert();
                    return driver.findElement(by); 
                }
        }
    
  • 递归处理
    一般情况下我们一次只会出现一个弹框,但是例外的是可能有一个以上的弹框同时出现,这样的话虽然处理了其中一个弹框,但是剩下的弹框依然会阻断用例的正常执行,这个时候就可以使用递归的方法,在处理完弹框后返回findElement方法自身,继续进行try catch,使之进入弹框处理逻辑
    public static WebElement findElement(By by) {
    	        try {
    	            System.out.println(by);
    	            return driver.findElement(by);
    	        } catch (Exception e) {
    	            System.out.println("进入弹框处理");
    	            handleAlert();
    	                return findElement(by); 
    	            }
    	    }
    
    注意: 使用递归方法后有一个问题,就是假如并不是因为某个弹框的出现而导致的定位失败,而这个时候通过try catch进入到弹框处理逻辑后,由于并未匹配到弹框元素,所以递归就会进入一个死循环,不断重复着弹框处理的逻辑,所以使用递归时我们也需要对其次数进行限制;一般两个弹框同时出现已经算多的了,所以建议可以将递归的次数限制到最多两次便退出。
    static int i = 1;
    public static WebElement findElement(By by) {
        try {
            System.out.println(by);
            return driver.findElement(by);
        } catch (Exception e) {
            if (i > 2){   //设置最多递归两次
                i = 1;
                return driver.findElement(by);
            }
            System.out.println("进入弹框处理第"+i+"次");
            handleAlert();
            i++;
            return findElement(by); //最后调用自身完成递归,防止多弹框同时出现造成定位失败
            }
    }
    
2.2.3 PageSource助力效率再提升

按照上面的方法,看似已经很好的解决了弹框的处理,但是可以注意到的是:

  • 在检查弹框的时候依然使用的是appium的定位,在当前页面中根据元素的属性去一一查找定位
  • 所有的黑名单中的弹框都会被定位查找一遍

而我们实际中最想要的也是最有效率的方法应该是:

  • 只有在当前页面中存在的弹框才对其进行定位、操作、处理。 为了达到我们想要的效果,就需要借助于PageSource了。

1)appiumdriver提供了一个getPageSource方法,此方法可以在当前页面可以得到一个文本字符串,也可以理解为当前页面的xml,我们利用这种xml文本来进行判断,就比用appium一一定位的方式要快速和精准的多了

String pageSource = driver.getPageSource();

2)设置黑名单,黑名单要使用元素的xpath,用来和PageSource文本做匹配,判断此弹框是否存在当前页面

String adBox = "com.xueqiu.android:id/ib_close";
String gesturePromptBox = "com.xueqiu.android:id/snb_tip_text";
String evaluateBox = "com.xueqiu.android:id/md_buttonDefaultNegative";

3)我们将黑名单中的xpath作为弹框查找的标记符,另外再定义一个定位符,用来找到弹框后做定位处理使用;这里可以将标记符定位符存入HashMap

HashMap<String,By> map = new HashMap<>();
map.put(adBox,By.id("ib_close"));
map.put(gesturePromptBox,By.id("snb_tip_text"));
map.put(evaluateBox,By.id("md_buttonDefaultNegative"));

4)遍历map,判断黑名单弹框元素是否存在于当前pageSource,存在即根据弹框处理方式进行点击或其他操作(如上述中的新功能提示弹框,点击弹框自身无法消除,需点击页面其余部分方可消除)处理
在这里插入图片描述

map.entrySet().forEach(entry ->{
    if (pageSource.contains(entry.getKey())){
        if (entry.getKey().equals("com.xueqiu.android:id/snb_tip_text")){
            System.out.println("gesturePromptBox found");
            Dimension size = driver.manage().window().getSize();
            //点击屏幕的中心位置,消除新功能提示弹框
            new TouchAction<>(driver).tap(PointOption.point(size.width/2,size.height/2)).perform();
        }else {
        	//其余弹框直接点击消除
            driver.findElement(entry.getValue()).click();
        }
    }
});

5)最后有一个小技巧,临时修改隐式等待时间,防止查找黑名单中元素过久,在弹框处理结束后再讲隐式等待时间复原;完整的方法实现如下:

//很多弹框的话,最好的是直接定位到到底哪个弹框在界面上,元素的判断使用xpath
    public static void handleAlertByPageSource(){
        String pageSource = driver.getPageSource();//可以得到一个文本字符串,也可以理解为当前页面的xml
        //黑名单
        String adBox = "com.xueqiu.android:id/ib_close";
        String gesturePromptBox = "com.xueqiu.android:id/snb_tip_text";
        String evaluateBox = "com.xueqiu.android:id/md_buttonDefaultNegative";

        //将标记和定位符存入map
        HashMap<String,By> map = new HashMap<>();
        map.put(adBox,By.id("ib_close"));
        map.put(gesturePromptBox,By.id("snb_tip_text"));
        map.put(evaluateBox,By.id("md_buttonDefaultNegative"));

        //临时修改隐式等待时间,防止查找黑名单中元素过久
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

        //遍历map,判断黑名单弹框元素是否存在于当前pageSource,存在即点击处理
        map.entrySet().forEach(entry ->{
            if (pageSource.contains(entry.getKey())){
                if (entry.getKey().equals("com.xueqiu.android:id/snb_tip_text")){
                    System.out.println("gesturePromptBox found");
                    Dimension size = driver.manage().window().getSize();
                    new TouchAction<>(driver).tap(PointOption.point(size.width/2,size.height/2)).perform();
                }else {
                    driver.findElement(entry.getValue()).click();
                }
            }
        });
        //判断完成后将隐式等待时间恢复
        driver.manage().timeouts().implicitlyWait(8,TimeUnit.SECONDS);
    }

6)最后将findElement方法中的handleAlert方法替换为handleAlertByPageSource方法即可

static int i = 1;
public static WebElement findElement(By by) {
    try {
        System.out.println(by);
        return driver.findElement(by);
    } catch (Exception e) {
        if (i > 2){   //设置最多递归两次
            i = 1;
            return driver.findElement(by);
        }
        System.out.println("进入弹框处理第"+i+"次");
        handleAlertByPageSource();
        i++;
        return findElement(by); //最后调用自身完成递归,防止多弹框同时出现造成定位失败
        }
}

3、首页判断

在第一部分中介绍的首页加载时候可能出现的坑:
App启动加载时间较久(可能App本身加载慢,可能移动设备本身加载应用速度慢,也可能首页广告时间较长);导致定位超时,用例失败。
对此我们又如下两步解决办法

3.1 首页元素显示等待

如标题所述,对首页进入使用显示等待,利用搜索控件的出现来判断是否进入了首页,这样不影响其他元素隐式等待的时间,也解决了首页初始化加载时间过长的问题;例如雪球仅在进入首页后会出现iduser_profile_container的用户信息控件,那么我们就可以以此为依据来判断应用是否加载完成进入了首页。
在这里插入图片描述

  • 在启动方法中加入显示等待上述首页控件30秒,到控件可被定位时确认进入首页
    new WebDriverWait(driver,30)
                    .until(ExpectedConditions.visibilityOfElementLocated(By.id("user_profile_container")));
    

缺点:
但是这样有个情况不能解决:若加载完成后有弹框出现,可能就一直无法定位到首页元素,但是实际上已经加载完成,比如下图的首页广告弹框
在这里插入图片描述

3.2 首页弹框判断

文章第二部分介绍了利用PageSource来判断弹框是否存在的方法,在这里依然适用,还是熟悉的味道,还是同样的套路,将弹框元素xpath也加入PageSource判断,这样无论首页控件和首页弹框哪一个被发现,就都可以判断应用已经加载完成,成功进入首页,剩下的就可以交给用例和其他处理逻辑了

new WebDriverWait(driver,30)
                .until(x ->{
                    String xml = driver.getPageSource();
                    Boolean checkResult = xml.contains("user_profile_container") || xml.contains("com.xueqiu.android:id/ib_close");
                    System.out.println("主页元素查找的结果是:" + checkResult);
                    return checkResult;
                });

4、运行效果展示

在这里插入图片描述

### Xapp1052 的 IT 相关内容或问题解决 根据已有的引用信息以及常见的技术场景,可以推测 xapp1052 可能涉及的应用领域和技术背景。以下是基于现有引用材料和专业知识的综合解答。 #### 一、可能的技术背景与关联 Xapp1052 如果是一个应用名称或者项目代号,则其潜在的技术挑战可以从以下几个方面推断: 1. **前置用例执行过程中的异常** 在某些情况下,如果应用程序在运行期间遇到未预期的行为(如异常窗),可能会干扰正常的业务流程[^1]。这种现象通常发生在自动化测试环境中,或者是用户交互逻辑设计不完善的情况下。建议通过捕获并处理这些异常事件来增强系统的稳定性。 2. **第三方 SDK 集成问题** 若 xapp1052 使用了特定的推送服务或其他功能插件(例如阿里云推送 SDK),则需要注意依赖管理不当可能导致的功能缺失或崩溃情况[^2]。确保所有必要的库文件均已正确引入,并验证相关接口调用的有效性。 3. **性能优化需求** 对于移动设备上的用户体验而言,流畅度至关重要。假设 xapp1052 是一款 Android 应用程序,在实际部署过程中难免面临诸如界面响应迟缓等问题[^4]。针对这些问题可采取如下措施: - 图片资源预先加载机制; - 列表项懒加载策略以减少内存占用; - 定期审查主线程操作是否存在阻塞行为。 #### 二、具体方案实施建议 ##### (一)实例为空状况下的改进办法 当检测到某个变量 `instance` 被赋值为 null 或者 undefined 时,应当重新审视初始化环节是否有遗漏之处。可以通过设置默认参数值或是提前判断条件分支的方式规避此类错误发生。 ```java if (instance == null || instance.isEmpty()) { initializeInstance(); // 自定义函数用于创建新对象 } ``` ##### (二)升级架版本带来的兼容性考量 随着 React Native 等跨平台工具不断迭代更新,开发者需密切关注官方文档说明以便及时调整配置选项适应最新标准。特别是涉及到底层架构变动的部分更要格外小心以免引发连锁反应影响整体结构稳定。 ##### (三)HTML5 打包至原生容器注意事项 对于采用 HBuilderX 工具构建轻量级混合型 APP 场景来说,支付模块往往成为整个工程中最复杂也是最容易出现问题的一环[^3]。因此务必遵循以下几点指导原则: - 明确区分线上环境同本地调试模式之间的差异; - 加密敏感数据传输通道防止被恶意截取篡改; - 测试阶段覆盖尽可能多的真实网络状态模拟真实世界使用情境。 --- ### 总结陈词 综上所述,围绕着名为 "xapp1052" 的主题展开讨论涵盖了多个层面的知识要点包括但不限于如何妥善处置因外部因素引起的中断情形;怎样合理规划外接组件间的协作关系从而降低耦合程度提高灵活性;最后还探讨到了有关提升视觉效果呈现速度方面的技巧分享等内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值