Hybrid 混合应用如何做自动化

准备条件

(1)准备一台系统版本5.0以上的安卓手机或者安卓模拟器
(2)安装一个辅助工具(pc端安装):uc-devtool(UC开发者工具,不需要翻墙),uc-devtool安装成功-》选择设置->勾选 本地Devtools inpsector资源

参考文章:https://www.cnblogs.com/yyoba/p/9969394.html
uc-devtool作用: 用来帮助定位app内嵌套的web页面元素信息

image.png

(3)被测试的app->需要打开Web调试开关->如何打开开关:

第一种方式:让开发在app源代码中加入一行代码(开发知道在哪里添加)-》再重新打包给到测试

WebView.setWebContentDebuggingEnabled(true);

webview(其实就是手机自带的系统应用)

负责web页面展示,解析,渲染web页面,其实就是微型的浏览器(帮助第三方app来展示web页面)
如下图使用appium无法定位到具体的元素信息,选择元素-》选中的是整块区域


image.png

webview每个手机都有这个应用,是以一个apk存在手机里面的,如何查看手机是否有webView?

手机-》设置->应用->全部


image.png

点击可以查看版本


image.png

问题: 可以使用文章text进行定位,但是text会变,所以这里需要借助uc-devtool获取元素定位信息

开发步骤

(1)uc开发者工具识别web页面的元素信息

打开uc-devtool: 设置-》勾选
没有打开app时,如下图没有检测到webView


image.png

进入到app主页(由于主页不是一个web页面,所以也没有检测到webView)


image.png

进入到web页面(柠檬社区),如下图,检测到了webView
下图中的:com.lemon.lemonban是app的包名
127.0.0.1:62001 ->是当前连接的设备名
74.0.3627.136是webView的版本


image.png

上图点击 inspect即可进入deBug控制台
如下图(其实就是根f12效果差不多),这样就可以使用web自动化提供的xpath等方式进行元素定位了


image.png

(2)开发脚本:

原生和web面需要切换context才能进行元素定位。
Context是在编写Android程序经常使用到的对象,意思为上下文对象。原生和网页属于不同的context

    @Test
    public void test() throws InterruptedException {
        //1.主页点击  柠檬社区
        androidDriver.findElementByAndroidUIAutomator("new UiSelector().text(\"柠檬社区\")").click();
        //2.等待web页面加载完成
        //这里不能使用隐式等待(不会生效)->因为:这里不是找元素,而是进行context切换,所以不会生效,只能用硬性等待
        
        Thread.sleep(8000);
        //3.获取到当前状态所有的context
        Set  contextHandles = androidDriver.getContextHandles();
        //打印出来看看-》打印结果:[NATIVE_APP,WEBVIEW_com.lemon.lemonban]
        System.out.println(contextHandles);
        //4.切换context-》根据web页面对应的context名字进行切换
        androidDriver.context("WEBVIEW_com.lemon.lemonban");
        Thread.sleep(2000);
        //5.web页面元素定位
        androidDriver.findElement(By.xpath("//a[@title=\"App 抓包提示网络异常怎么破?\"]")).click();
    
    }


执行上面代码。如果报错,请看下面的注意(5)

注意

(1) 原生页面对应的context->是NATIVE_APP
不管你是主页还是登录页,只要是原生的页面,对应的context就是NATIVE_APP
(2)Web页面对应的context->是 WEBVIEW_com.lemon.lemonban

(3)打开app之后默认是在原生的context中,所以如果要定位web页面中的元素,需要切换context

(4)context切换之后,对web页面元素进行元素定位,为什么依然使用androidDriver,而不是( ie,firefox,chrome对应的driver呢)-->这是因为:Appium自带chromedriver,内部会进行driver驱动的替换,会把原来的androidDriver替换成chromedriver->为什么不是 IE,firrfox的driver呢,因为安卓系统是chrome开发的,webView也是chrome开发的,所以自动替换的就是chromeDriver
(5)webView和chromedriver版本不对应-》上面代码执行console会报下面错误

io.appium.java_client.NoSuchContextException: An unknown server-side error occurred while processing the command. Original error: No Chromedriver found that can automate Chrome '74.0.3729'. See https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md for more details.
Build info: version: '3.12.0', revision: '7c6e0b3', time: '2018-05-08T14:04:26.12Z'

appium报错日志如下:


image.png

根据报错信息可以知道:webView和chromedriver版本不匹配导致的

解决办法:

(1)找到appium自带的chromeview安装路径:

查看版本:


image.png

(2)模拟器查看系统自带的webview版本:
手机设置-》应用-》全部


image.png

(3)查看版本对照表
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md

image.png

appium自带的chromedriver版本是:75 ,模拟器自带的webView版本是74
参考版本对照表:webview71对应chromedriver是2.46 ,没有webview74版本,不过我们这里先下载2.46的试试看(下载完成后,将原来的chromedriver覆盖更新即可):结果发现是还是报凑

ChromeDriver 2.39 and newer require adb version 1.0.38 or newer. Run 'adb version' in your terminal of the host device to find your version of adb.

上面的报错信息说的是:
ChromeDriver 2.39及更高版本需要adb 1.0.38或更高版本。在主机设备的终端中运行“adb version”以查找adb的版本。
下图发现我的adb版本太低【1.0.36】【这里的adb用的是模拟器中的adb,因为之前sdk 自己的adb和模拟器中的adb版本不对应导致adb connect连接失败-》解决办法:将sdk中的adb替换成模拟器中的adb】


image.png

现在需要怎么解决呢?-》升级adb版本:将模拟器中adb换成sdk中的adb,sdk还用自己的adb


image.png

adb替换ok,需要重启adb,重启命令:adb kill-server,重启完adb后,再输入adb devices ,adb就会自动起来
再重新执行代码:发现context切换成功,下面代码可以定位到元素。

androidDriver.findElement(By.xpath("//a[@title=\"App 抓包提示网络异常怎么破?\"]")).click();

注意:这里为什么不是对webview进行升级而是替换chromeDriver呢?
因为:手机自带的webview升级很麻烦

(6)当回到原生页面进行测试时,需要将context切换回来

@Test
    public void test() throws InterruptedException {
        // 1.主页点击 柠檬社区
        androidDriver.findElementByAndroidUIAutomator("new UiSelector().text(\"柠檬社区\")").click();
        // 2.等待web页面加载完成
        // 这里不能使用隐式等待(不会生效)->因为:这里不是找元素,而是进行context切换,所以不会生效,只能用硬性等待

        Thread.sleep(8000);
        // 3.获取到当前状态所有的context
        Set contextHandles = androidDriver.getContextHandles();
        // 打印出来看看-》打印结果:[NATIVE_APP,WEBVIEW_com.lemon.lemonban]
        System.out.println(contextHandles);
        // 4.切换context-》根据web页面对应的context名字进行切换
        androidDriver.context("WEBVIEW_com.lemon.lemonban");
        Thread.sleep(2000);
        // 5.web页面元素定位
        androidDriver.findElement(By.xpath("//a[@title=\"App 抓包提示网络异常怎么破?\"]")).click();
        // 6.回到主页
        // 6.1当回到原生页面中进行元素定位时,context需要切换回来(由于左上角x是在原生页面里面,需要需要切换,否则定位不到)
        androidDriver.context("NATIVE_APP");
        // 6.2定位到x按钮->退出
        androidDriver.findElement(By.className("android.widget.ImageButton")).click();
        // 6.3定位确定按钮-》确定 退出到主页
        androidDriver.findElement(By.id("com.lemon.lemonban:id/tv_sure")).click();

    }

如果context不切换,就会报如下错误:

org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"class name","selector":"android.widget.ImageButton"}

app中使用浏览器打开web页面,代码怎么写?

(1)如果使用的浏览器是手机系统自带的apk
那么如何获取浏览器apk的包名和启动入口呢?-》解决办法:将手机中的apk拉取到pc端


image.png
image.png

(2)再使用aapt解析apk的包名和启动入口
(3) 地址栏是原生的 用Androiddriver sendkeys方法 再输入enter键操作
androidDriver.get(url)这种是不可以的

你可能感兴趣的:(Hybrid 混合应用如何做自动化)