混合 H5 应用 UI 自动化进阶

混合 H5 应用 UI 自动化是移动应用自动化中无法绕过的一节,针对混合 H5 应用的 UI 自动化入门之前已经写过一篇文章:https://testerhome.com/topics/9651 ,入门的同学可移步学习。本文主要针对 H5 应用 UI 自动化高级使用进行一些分享。

如何定位元素

参考上述入门文章:https://testerhome.com/topics/9651

进阶

本文中所涉及的 demo 示例代码已开源:

https://github.com/macaca-sample/macaca-java-biz-sample

H5 基础知识储备

要对 H5 应用进行 UI 自动化,首先要掌握一些基础的 H5 知识,HTML,CSS,JQuery 这些是最基础的,建议有此类需求的同学先简单补充下此类基础知识,主要是选择器以及事件触发等,笔者主要参考的是 W3school 的教程,教程地址如下http://www.w3school.com.cn/。掌握了最基础的 H5 知识,就可以进入下一步了。

H5 内多个 webview 跳转后操作失败

部分同学反馈,自动化中当从一个 H5 页面跳转到另一个 H5 页面后对新的 H5 页面的操作无效,这大部分是因为 H5 页面内发生跳转后没有更新上下文导致的,当我们从 Native 进入一个 H5 页面后,当前上下文会存在两个,一个是 Native,一个是 webview,但是当 webview 内发生跳转时,也会生成新的上下文,比如当我们从上面这个 H5 跳转到另一个页面后,此时的上下文信息如下:

responseHandler.js:49:14 [master] pid:62034 Send HTTP Respone to Client[2017-11-08 20:45:31]: {"sessionId":"fecd1f1b-1ca4-4c54-9905-97a7af0c0a52","status":0,"value":"[\"NATIVE_APP\",\"CDwindow-b35eb442-86e4-4dec-913d-ea3b0b69bf6a\",\"CDwindow-59160ffd-74f4-4425-949a-30eb52786ba0\"]"}

这里面我们可以发现 NATIVE_APP 表示 Native 的上下文,两个 CDWindow 代表的是两个 H5 页面,此时如果要对上层的 H5 页面操作,则必须更新当前上下文到栈顶的上下文,在 biz 层提供了用于上下文更新的 API,如下:

/**
     * 当存在多个上下文时,切换当前上下文为当前最顶部的window,当webview发生跳转时可以通过此API更新上下文
     * @throws Exception
     */
    public void updateTopContext() throws  Exception {
        JSONArray contexts = contexts();
        this.context(contexts.get(contexts.size() - 1).toString());
    }

万能的 'driver.execute()'

Macaca 提供了一些常用的 H5 操作的 API,但有些时候这些 API 无法满足我们的特殊需要,比如我们想拿到页面内所有的跳转链接并跳转以此来完成二级页面的遍历,此时已有的 API 显然无法满足我们的需要,这时候就需要用到 driver.excute(),excute() API 可以用来执行 js 脚本,如此,我们便可以执行任何可以通过 js 脚本实现的功能,比如我们的 demo 中百度页面的 href 属性基本上表示了可跳转的二级页面链接,那我们可以通过如下代码实现二级页面遍历的需求:

如下代码在 com.javademo.cases.SampleTest 中,可前往https://github.com/macaca-sample/macaca-java-biz-sample查看

// com.javademo.cases.SampleTest
public void  iterateBaiDuPage() throws  Exception{
        JSONObject schemaJson = driver.execute("var arr=[];function getSchemas(){$.each($('[href]'),function(index,item){arr.push(item.getAttribute('href'))}); return arr;};return getSchemas();");
        JSONArray schemas = schemaJson.getJSONArray("value");
        System.out.println("schemas===========" + schemas);

        if (schemas!=null && schemas.size() > 0) {
            // 循环进入各个二级跳转链接
            for (int i = 0; i < schemas.size(); i++) {

                String tmpHref = (String) schemas.get(i);
                String jsCode = "location.assign(\"" + tmpHref + "\")";
                driver.execute(jsCode);
                driver.sleep(3000);
                saveScreen(tmpHref);

                driver.execute("history.back();");

            }

        }
    }

在编写如上脚本所需要的 js 脚本时,我们可以在 inspector 页面的 console 中先进行调试,调试成功后放入 driver.excute('') 中执行,如下:
img

如此,通过 driver.execute(),我们便可以实现通过 js 脚本能够实现的功能,是不是很强大呢。

注意事项

有其他问题,欢迎补充讨论。


↙↙↙阅读原文可查看相关链接,并与作者交流