问题描述

在测 APP 的业务流,WebView 和 Native 模式耦合在一起。例如:WebView >> Native >> WebView >> 。。。。。。
Appium 貌似有个问题,从 WebView 切换到 NATIVE 后,chromedriver 可能会把第一个 WebView 的缓存驻留在内存中,即便用 driver.close() 方法关闭当前上下文,也无法清除。
这样会导致进入其他的 WebView,读取的还是第一个 WebView 的内容,导致页面元素无法识别。
下面是发现问题到解决问题的一个过程,希望能帮助到遇到过同样问题的同行。

第一版代码:可能大多数人开始都会这么写,这样可能导致无法识别到其他窗口 WebView 的内容。

public void testDemo() {
        try {
            Log.logInfo("开始切换到WebView模式");
            ((AppiumDriver) driver).context("WEBVIEW_com.xx.xx.xx.xx");
            Log.logInfo("成功切换到WebView模式,开始查找WebView元素");
            driver.findElement(By.cssSelector("#myWeidian > div.tpl_part > ul > li.second > span")).click();
            driver.findElement(By.cssSelector("#myWeidian > div.tpl_part > ul > li.last > span")).click();
            driver.findElement(By.cssSelector("#myWeidian > div.tpl_part > div")).click();
            Log.logInfo("开始切换到NATIVE模式");
            ((AppiumDriver) driver).context("NATIVE_APP");
        } catch (Exception e) {
            // anything
        }
    }

第二版代码:我的思路是想通过正常途径解决问题,把当前 WebView 的实例赋给临时对象,用完后调用 close() 方法(quit() 会把整个 Seesion 关闭),还是以失败告终,有点发吼了。

public void testDemo() {
        try {
            Log.logInfo("开始切换到WebView模式");
            AppiumDriver chromeDriver = (AppiumDriver) ((AppiumDriver) driver).context("WEBVIEW_com.xx.xx.xx.xx");
            Log.logInfo("成功切换到WebView模式,开始查找WebView元素");
            chromeDriver .findElement(By.cssSelector("#myWeidian > div.tpl_part > ul > li.second > span")).click();
            chromeDriver .findElement(By.cssSelector("#myWeidian > div.tpl_part > ul > li.last > span")).click();
            chromeDriver .findElement(By.cssSelector("#myWeidian > div.tpl_part > div")).click();
            chromeDriver.close();
            Log.logInfo("开始切换到NATIVE模式");
            ((AppiumDriver) driver).context("NATIVE_APP");
        } catch (Exception e) {
             // anything
        }
    }

第三版代码:软的不行来硬的,放了个绝招,杀 chromedriver 的进程,还真的成功了,有时候真的需要暴力。。。

public void testDemo() {
        try {
            Log.logInfo("开始切换到WebView模式");
            ((AppiumDriver) driver).context("WEBVIEW_com.xx.xx.xx.xx");
            Log.logInfo("成功切换到WebView模式,开始查找WebView元素");
            driver.findElement(By.cssSelector("#myWeidian > div.tpl_part > ul > li.second > span")).click();
            driver.findElement(By.cssSelector("#myWeidian > div.tpl_part > ul > li.last > span")).click();
            driver.findElement(By.cssSelector("#myWeidian > div.tpl_part > div")).click();
            Log.logInfo("开始切换到NATIVE模式");
            ((AppiumDriver) driver).context("NATIVE_APP");
            Tools.killProcess("chromedriver");
        } catch (Exception e) {
            Tools.killProcess("chromedriver");
        }
    }

    public static void killProcess(String processName) {
        try {
            String cmd = isWindows() ? "tskill " + processName : "killall \"" + processName + "\"";
            cmdInvoke(cmd);
        } catch (Exception e) {
            Log.logInfo(e.getMessage());
        }
    }

    public static String cmdInvoke(String cmd) {
        String cmdOut = "";
        BufferedReader br = null;

        try {
            Process p = Runtime.getRuntime().exec(cmd);
            br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null) {
                cmdOut = line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return cmdOut;
    }


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