Appium之Hybrid APP混合应用测试

目录

前言

1. 解决方案

2. 遇到的问题

2.1 contexts只能获取NATIVE_APP,无法获取WEBVIEW

2.2 已经能够获取到WEBVIEW,但是无法切换到WEBVIEW


前言

在web自动化中我们会遇见frame的问题,在遇见这些内嵌的标签后我们需要做的就是切换窗口,那么在app自动化测试也有类似的情况就是我们经常看见的内嵌h5,即在我们原生的app中增加一个由html做成的页面。这种应用我们称为Hybrid app移动混合应用程序,即在移动应用程序中嵌入了Webview,通过Webview访问网页。

webView是Android系统提供能显示网页的系统控件,它是一个特殊的View,同一时候它也是一个ViewGroup能够有非常多其它子View。在Android 4.4以下(不包括4.4)系统WebView底层实现是採用WebKit(WebKit)内核,而在Android 4.4及其以上Google 採用了chromium(http://www.chromium.org/)作为系统WebView的底层内核支持。在这一变化中Android 提供的WebView相关API并没有发生大变化,在4.4上也兼容低版本号的API而且引进了少部分API。基于Chromium Webview提供更广的HTML5,CSS3,Javascript支持,另外Chromium 支持远程调试(Chrome DevTools)。

1. 解决方案

1.切换到Webview的Context下

移动应用和Webview分别属于两个不同的上下文,移动应用默认的Context为“NATIVE APP",Webview默认的Context为“WEBVIEW_+被测进程名称”。测试Webview中的网页内容时,需要切换到Webview的Context下。

python代码如下:

for cons in driver.contexts:
    if cons.lower().startswith("webview"):
        driver._switch_to.context(cons)
        break
# 或

cons = driver.contexts  # 获取上下文列表
driver._switch_to.context(cons[-1])

java代码如下:

Set<String> contextNames = driver.getContextHandles();
        for (String contextName : contextNames) {
        	// 用于返回被测app是NATIVE_APP还是WEBVIEW,如果两者都有就是混合型App
            System.out.println(contextName); 
            if(contextName.contains("WEBVIEW")){
            	// 让appium切换到webview模式以便查找web元素
                driver.context(contextName);
                System.out.println("切换到webview:"+contextName);
            }
        }

2.切回到NATIVE APP

操作完webview了记得切回到NATIVE APP。

python代码如下:

driver._switch_to.context("NATIVE_APP")

java代码如下:

driver.context(NATIVE APP);

2. 遇到的问题

切换WebView时可能会遇到问题,导致无法进行WebView切换,可能有以下原因。

2.1 contexts只能获取NATIVE_APP,无法获取WEBVIEW

使用uiautomatorviewer定位元素,显示class值为:android.webkit.WebView

但是driver.contexts只打印出了‘NATIVE_APP’;

>>> driver.contexts
['NATIVE_APP']

第一种情况:

Android 4.4以上,未开启webview远程调试功能。

【解决方案】

需要开启webview远程调试功能, Android 4.4以上,需要在应用代码中增加一下代码段开启该功能 (可由开发人员增加后重新打包给测试):

修改Activity extends CordovaActivity,设置setWebContentsDebuggingEnabled(true);

public class MyActivity  extends CordovaActivity {
    CordovaWebView cwv;
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.init();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            this.appView.setWebContentsDebuggingEnabled(true);
        }
        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);
    }
}

开启WebView远程调试功能后,重新打印contexts,成功!

>>> driver.contexts
['NATIVE_APP', 'WEBVIEW_com.sxxxxx.xxx']

第二种情况:

测试手机不是android4.4以上的版本。而4.4以下版本的Webview没有使用Chrome内核,只有在Selendroid模式中才支持4.4以下的内核。所以需要在Desired Capabilities中添加这句代码:

SetCapability("automationName") = "Selendroid";

第三种情况:

程序中使用的Webview不是Chrome内核。而Appian只支持Chrome内核。所以Appium就不能获取该Webview的Context。例如腾讯的X5内核。

2.2 已经能够获取到WEBVIEW,但是无法切换到WEBVIEW

查看Appium 

# 发送contexts命令
> info: --> GET /wd/hub/session/c759114f-617f-461b-8341-91ca1d25515c/contexts {}> info: [debug] Getting a list of available webviews> info: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe -s f825d6cd shell "cat /proc/net/unix"> info: [debug] WEBVIEW_16429 mapped to pid 16429> info: [debug] Getting process name for webview> info: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe -s f825d6cd shell "ps"> info: [debug] Parsed pid: 16429 pkg: com.package.name> info: [debug] from: u0_a256,16429,502,1975592,128716,ffffffff,00000000,S,com.package.name> info: [debug] returning process name: com.package.name> info: [debug] Available contexts: > info: [debug] ["WEBVIEW_com.package.name"]> info: [debug] Available contexts: NATIVE_APP,WEBVIEW_com.package.name
# 此处显示已成功将contexts响应给client,["NATIVE_APP","WEBVIEW_com.package.name"]> info: [debug] Responding to client with success: {"status":0,"value":["NATIVE_APP","WEBVIEW_com.package.name"],"sessionId":"c759114f-617f-461b-8341-91ca1d25515c"}> info: <-- GET /wd/hub/session/c759114f-617f-461b-8341-91ca1d25515c/contexts 200 395.699 ms - 112 {"status":0,"value":["NATIVE_APP","WEBVIEW_com.package.name"],"sessionId":"c759114f-617f-461b-8341-91ca1d25515c"}> info: --> POST /wd/hub/session/c759114f-617f-461b-8341-91ca1d25515c/context {"sessionId":"c759114f-617f-461b-8341-91ca1d25515c","name":"WEBVIEW_com.package.name"}> info: [debug] Getting a list of available webviews> info: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe -s f825d6cd shell "cat /proc/net/unix"> info: [debug] WEBVIEW_16429 mapped to pid 16429> info: [debug] Getting process name for webview> info: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe -s f825d6cd shell "ps"> info: [debug] Parsed pid: 16429 pkg: com.package.name> info: [debug] from: u0_a256,16429,502,1975592,128716,ffffffff,00000000,S,com.package.name> info: [debug] returning process name: com.package.name> info: [debug] Available contexts: NATIVE_APP,WEBVIEW_com.package.name> info: [debug] ["WEBVIEW_com.package.name"]> info: [debug] Available contexts: NATIVE_APP,WEBVIEW_com.package.name
# 开始调用启动Chromedriver> info: [debug] Connecting to chrome-backed webview> info: Chromedriver: Changed state to 'starting'> info: Chromedriver: Set chromedriver binary as: D:\Appium\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win\chromedriver.exe> info: Chromedriver: Killing any old chromedrivers, running: FOR /F "usebackq tokens=5" %a in (`netstat -nao ^| findstr /R /C:"9515 "`) do (FOR /F "usebackq" %b in (`TASKLIST /FI "PID eq %a" ^| findstr /I chromedriver.exe`) do (IF NOT %b=="" TASKKILL /F /PID %a))> info: Chromedriver: No old chromedrivers seemed to exist> info: Chromedriver: Spawning chromedriver with: D:\Appium\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win\chromedriver.exe --url-base=wd/hub --port=9515> info: Chromedriver: [STDOUT] Starting ChromeDriver 2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a) on port 9515> Only local connections are allowed.> info: JSONWP Proxy: Proxying [GET /status] to [GET http://127.0.0.1:9515/wd/hub/status] with no body> info: JSONWP Proxy: Got response with status 200: "{\"sessionId\":\"\",\"status\":0,\"value\":{\"build\":{\"version\":\"alpha\"},\"os\":{\"arch\":\"x86_64\",\"name\":\"Windows NT\",\"version\":\"10.0\"}}}"> info: JSONWP Proxy: Proxying [POST /session] to [POST http://127.0.0.1:9515/wd/hub/session] with body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"com.package.name","androidUseRunningApp":true,"androidDeviceSerial":"f825d6cd"}}}> info: JSONWP Proxy: Got response with status 200: {"sessionId":"448c057dd8e679591a99e539a6485d45","status":13,"value":{"message":"unknown error: Device f825d6cd is not online\n (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d...> info: JSONWP Proxy: Proxying [POST /session] to [POST http://127.0.0.1:9515/wd/hub/session] with body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"com.package.name","androidUseRunningApp":true,"androidDeviceSerial":"f825d6cd"}}}> info: JSONWP Proxy: Got response with status 200: {"sessionId":"a2c6259b846570c32fa66f07b8e663ba","status":13,"value":{"message":"unknown error: Device f825d6cd is not online\n (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d...> info: JSONWP Proxy: Proxying [POST /session] to [POST http://127.0.0.1:9515/wd/hub/session] with body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"com.package.name","androidUseRunningApp":true,"androidDeviceSerial":"f825d6cd"}}}> info: JSONWP Proxy: Got response with status 200: {"sessionId":"44a889342086cf78ea724e48b0958960","status":13,"value":{"message":"unknown error: Device f825d6cd is not online\n (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d...> info: JSONWP Proxy: Proxying [POST /session] to [POST http://127.0.0.1:9515/wd/hub/session] with body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"com.package.name","androidUseRunningApp":true,"androidDeviceSerial":"f825d6cd"}}}> info: JSONWP Proxy: Got response with status 200: {"sessionId":"66c261de9b5c1919eee22072feb2fa2e","status":13,"value":{"message":"unknown error: Chrome version must be >= 43.0.2357.0\n (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb51...
# Chromedriver开始报错!> error: Chromedriver: Chromedriver exited unexpectedly with code null, signal SIGTERM> info: Chromedriver: Changed state to 'stopped'> warn: Chromedriver for context WEBVIEW_com.package.name stopped unexpectedly> warn: Chromedriver quit unexpectedly, but it wasn't the active context, ignoring
# 此处报了重要的错误信息:Chrome version must be >= 43.0.2357.0,chromedriver=2.18.343845> error: Chromedriver: Error: An unknown server-side error occurred while processing the command. (Original error: unknown error: Chrome version must be >= 43.0.2357.0> (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a),platform=Windows NT 10.0 x86_64))> at JWProxy.command$ (lib/proxy.js:133:15)> at tryCatch (D:\Appium\node_modules\appium\node_modules\appium-chromedriver\node_modules\appium-jsonwp-proxy\node_modules\babel-runtime\regenerator\runtime.js:67:40)> at GeneratorFunctionPrototype.invoke [as _invoke] (D:\Appium\node_modules\appium\node_modules\appium-chromedriver\node_modules\appium-jsonwp-proxy\node_modules\babel-runtime\regenerator\runtime.js:315:22)> at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (D:\Appium\node_modules\appium\node_modules\appium-chromedriver\node_modules\appium-jsonwp-proxy\node_modules\babel-runtime\regenerator\runtime.js:100:21)> at GeneratorFunctionPrototype.invoke (D:\Appium\node_modules\appium\node_modules\appium-chromedriver\node_modules\appium-jsonwp-proxy\node_modules\babel-runtime\regenerator\runtime.js:136:37)> at bound (domain.js:284:14)> at GeneratorFunctionPrototype.runBound (domain.js:297:12)> at run (D:\Appium\node_modules\appium\node_modules\appium-chromedriver\node_modules\appium-jsonwp-proxy\node_modules\babel-runtime\node_modules\core-js\library\modules\es6.promise.js:89:39)> at D:\Appium\node_modules\appium\node_modules\appium-chromedriver\node_modules\appium-jsonwp-proxy\node_modules\babel-runtime\node_modules\core-js\library\modules\es6.promise.js:100:28> at flush (D:\Appium\node_modules\appium\node_modules\appium-chromedriver\node_modules\appium-jsonwp-proxy\node_modules\babel-runtime\node_modules\core-js\library\modules\$.microtask.js:17:13)> at process._tickDomainCallback (node.js:381:11)> { [Error: An unknown server-side error occurred while processing the command. (Original error: unknown error: Chrome version must be >= 43.0.2357.0> (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a),platform=Windows NT 10.0 x86_64))]> status: 13,> value: { message: 'unknown error: Chrome version must be >= 43.0.2357.0\n (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a),platform=Windows NT 10.0 x86_64)' },> httpCode: 200 }

webview控件使用的是Android自带的chrome内核,那么来看看手机自带的chrome内核版本吧;

设置>应用程序管理>全部,查找到Android System WebView应用,查看详情,显示版本号:42.0.2311.138

由此可知,Android系统自带的chrom内核版本过低,造成报错;

【解决方案】

知道了报错原因,那么来进行问题解决吧。

方案1:

根据报错信息要求的版本,下载更新Android System WebView;

方案2:

从报错信息得知Appium使用的chromedriver=2.18.343845

查看ChromeDriver官网,得知ChromeDriver2.18支持Chrome 44+

So,我们可以更新下载对应版本的ChromeDriver.exe替换D:\Appium\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win\chromedriver.exe

所有版本ChromeDriver下载地址

注:

双击执行“chromedriver.exe”,可以查看版本driver版本号;

参考文章:

1.Appium Hybrid混合应用测试——Native切换WebView

2.使用Appium测试Hybrid App的方法

3.Android 各个版本号WebView

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕城南风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值