Appium Appium WebView 初探

Stepthen · 2015年11月10日 · 最后由 Stepthen 回复于 2017年07月26日 · 219 次阅读

公司的 App 是 Native App,看大家经常在网上问 WebView 的问题,自己也尝试了一下,也有一些疑问,望高手们指导。测试 APP 为网上随便找的 APP。

疑问:

  1. 在 WebView 界面获取 Contexts 的值中,只获取到一个 NATIVE_APP 值,没有获取到 WebView 值;后来测试官网的 donet 的实例,在 WebView 界面获取到的也只有 NATIVE_APP 的值,而网友说 Java 语言的是可以获取到的,有没有遇到这种问题的,期望回答一下?

答:
获取 Webview 需要开发 app 的工程师在代码中添加开启 webview 调试的代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    WebView.setWebContentsDebuggingEnabled(true);
}

注:有时候会获取到多个 webiew 的 Context,切换时要切换成自己 app 对应的 webview.

  1. 代码中并没有用命令 Context 进行切换到 WebView,但仍然是可以访问的,这是怎么回事呢?不切换 Context 也可以控制 WebView 页面,难道是新版本的 Appium 已经自动识别,不用在 Native 和 WebView 切换了吗?
    答:
    对于混合型 APP,在 webview 界面有些元素的操作是不需要切到 webview 操作的,但使用比如 js 操作等是需要切换到 webview 的。

  2. 测试 WebView 的 App 一般用什么方法查看控件的?也是用 UI Automator Viewer 查看吗,有没有更好的方法?
    答:
    用 UI Automator Viewer 或 appium 自带的 inspector

测试环境:

手机型号: 三星 Galasy S6
系统版本: Android5.1.1
编程语言: donet
Appium 版本: 1.4.0.0

截图

手动启动 app 后,用 UI Automator Viewer 查看:

Appium 启动后,用 UI Automator Viewer 查看:

测试代码:

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability("BrowserName", "");
//capabilities.SetCapability("automationName", "selendroid");
capabilities.SetCapability("deviceName", "Android Emulator");
capabilities.SetCapability("platformName", "Android");
capabilities.SetCapability("platformVersion", "4.4");
capabilities.SetCapability("newCommandTimeout", "300");

capabilities.SetCapability("unicodeKeyboard", "True");
capabilities.SetCapability("resetKeyboard", "True"); 

capabilities.SetCapability("appPackage", "com.facishare.fs");
capabilities.SetCapability("appActivity", "com.facishare.fs.IndexActivity");

Uri serverUri = new Uri("http://127.0.0.1:4723/wd/hub");
driver = new AndroidDriver<AndroidElement>(serverUri, capabilities, TimeSpan.FromSeconds(180));
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1));

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
IWebElement element = wait.Until<IWebElement>((d) =>
{
    return driver.FindElementByName("注册");
});

element.Click();
driver.FindElementByName("创建一个新企业,全新注册").Click();
Thread.Sleep(2000);

//webView界面, 疑问:此处获取到的contexts只有一个值NATIVE_APP,所以下面并没有对Context进行切换操作
var contexts = ((IContextAware)driver).Contexts;
string webviewContext = null;
for (int i = 0; i < contexts.Count; i++)
{
    Console.WriteLine(contexts[i]);
    if (contexts[i].Contains("WEBVIEW"))
    {
        webviewContext = contexts[i];
    }
}

Assert.IsTrue(driver.PageSource.Contains("新用户注册"));
driver.FindElementByName("请输入手机号").SendKeys("13890888555");
driver.FindElementByName("输入图中字符").SendKeys("kkejd");
driver.FindElementByName("获取验证码").Click();
driver.FindElementByName("确定").Click();
driver.FindElementByName("输入验证码").SendKeys("11111");
driver.FindElementByName("下一步").Click();

driver.Quit();
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 29 条回复 时间 点赞

没看明白,你是提问题,还是解决了问题。。。建议修改下帖子

你是纷享销客的拖吧。。。

#2 楼 @lihuazhang @xushizhao 主要是在 android6.0 上都运行不起来

说下我自己的经验
第一个问题一般是由于 webview 没有开调试:

For a real device you need to have "setWebContentsDebuggingEnabled" in the web view. Without it the web view is not exposed to automation tools

所以对应的 webview 需要增加:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    WebView.setWebContentsDebuggingEnabled(true);
}

第三个问题:
Remote Debugging on Android with Chrome 看看这个吧,。

至于第二个问题实在不清楚。

#1 楼 @lihuazhang ,不好意思,语文不好,改了一下。另外我不是拖,既然有这怀疑,我就把下载链接给删了。

#6 楼 @happystone 昨晚身边只有台 6.0 的手机,运行不起来。

#5 楼 @zsx10110 ,非常感谢,学习了。

#7 楼 @lihuazhang ,报什么错呢?我这边没有 android 6.0 的机器。另外 纷享销客 跟我没什么关系,我只是拿他们的软件来学习的。

新手提问啊: 之前一直用 monkeyrunner+python 来做自动化, 现在想换到 appium 上。 目前遇到个问题, 如何检查某个元素 ID 是否在当前界面中? 目前用的 self.driver.find_element_by_id , 一旦找不到, 脚本就退出了。。 然后抛出异常: an element could not be located on the page using the given search parameters..

我想实现的是每做一部操作前 先判断 ID 是不是在当前界面,所以找不到 ID 就退出这个很致命啊
monkeyrunner 中可以用 viewer.visible(button) 来判断, appium 用什么判断呢

#11 楼 @lylyliuyu ,加个 try catch 处理,抓到异常别抛就好啦

#12 楼 @happystone 这么简单粗暴 ∑(O_O;) 我以为 appium 这种新出来的会有高级用法,然而看 api 文档也没发现……

希望越做越好!

#13 楼 @lylyliuyu ,貌似 appium 确实没有像 monkeyRunner 和 Espresso 一样判断页面加载的方法。

#10 楼 @lihuazhang,可能他们的 APP 的兼容问题的吧,我们暂时就不关注它了吧。你那边有测过带 webView 的 APP 吗,平时测试时是否需要切换这个 Context,我在想是不是有些 APP 必须切换,有些不需要?

新手提问一下:

at Layer.handle as handle_request
at trim_prefix (D:\Appium\node_modules\appium\node_modules\express\lib\router\index.js:302:13)
info: [debug] Responding to client with error: {"status":33,"value":{"message":"A new session could not be created. (Original error: Requested a new session but one was in progress)","origValue":"Requested a new session but one was in progress"},"sessionId":"8b38998e-576f-49b5-a0b7-993132c240b4"}
info: <-- POST /wd/hub/session 500 10.144 ms - 250
新手提问一下:请问这个是什么问题?

#18 楼 @243885978 ,是你前一个 session 未关掉吧,把 appium 停止 重新开启应该就 Ok;用例测试结束后需要用 “driver.Quit();” 关闭 session

#19 楼 @happystone 有这可能,第一次运行脚本就会卡在 info: [debug] Checking whether adb is present 不动,第二次运行就会出现上面那个,那第一次的提示是哪里没配置对吗?

#5 楼 @zsx10110 关于第 2 点,我也遇到这种现象,不切换可以和 native 一样去识别,难道我们对这句话的理解有问题?(For a real device you need to have "setWebContentsDebuggingEnabled" in the web view. Without it the web view is not exposed to automation tools)是否暴露和能否识别是两码事?回头再研究下。。。

@zsx10110 @happystone
最近在研究如何在手机上识别 WebView 元素,我用最新的 Appium Inspector 查看天猫 Apk,点击 Refresh,通过日志发现它把 apk 做了 debug 重签名,然后调用了 Bootstrap 里面的 source 命令,在 Inspector 的界面上就可以看到当前 App 页面的控件树。
想请教大家,Refresh 操作是通过 source 实现的吗?能够直接获取到 WebView 的内容?
https://github.com/appium/appium/blob/master/lib/devices/android/android-hybrid.js又在什么时候起的作用呢?
最重要的问题是不依赖 PC 端的 chromedriver,能直接在手机端获取 WebView 元素么?
还请大家不吝赐教,谢谢了!我的 QQ 号是 348940981,

#5 楼 @zsx10110 我的打开了 debug,但是 Build.VERSION.SDK_INT 获取到是 0?怎么办呢?这样的话设了也没有用啊

请问混合型 APP,在 webview 界面有些元素的操作是不需要切到 webview 操作的,但是当需要进入 native 页面时怎么处理?contexts 发现页面只有 native,但是触发 native 控件时就不能进入 native 页面或者调起 native 控制;如果 swich_to.context 切换到 native 页面,也是没效果的,因为根本没进入 native 页面。请问大家遇到过没?是怎样处理的?@happystone @Lihuazhang

小暖ljj 回复

@xiaonuanljj ,页面跳转和切换 contexts 是两回事;切换 contexts 是为了操作 webview 页面里元素,比如有些元素操作不了,可以切换到 webview 后,用 JS 的方法去操作元素;页面跳转是需要你点击对应的跳转按钮,或者使用 back 键等来操作切换页面。不知道你具体遇到啥问题。

Stepthen 回复

我这边是启动 APP 时直接进入 webview 页面,用 appiumdriver 直接操作的 webview 页面元素(通过 UI Automator viewer 可以查看到 id text classname 等元素),webview 页面中调用了一些 native 的控件,当点击吊起 native 的控件时,click 操作不生效(手动点击没问题可以吊起,UI case 跑就不能吊起)。考虑如下:1.没切换到 native,所以掉不起来 -------- 实际进行切换依然不通 2.click 不生效,使用 tab 等 ----- 不通 3.吊起 native 控件是否重新开了一个页面 ------ 用 selenium 一些切换 handle 的方法,不通 已经不知道是什么原因了,求帮助~

  1. webview 模式下尝试 JS 的方式点击
    IJavaScriptExecutor excutor= (IJavaScriptExecutor) driver;
    excutor.ExecuteScript(String.Format("arguments[0].{0}", "click()"), element);

  2. 可以获取元素的坐标,用 TcouchAction 的方式点击

Stepthen 回复

多谢,不过两种方法都不可行,均尝试过。看到其他文章说可能是多个窗口的原因,但是我这边是 appiumdriver 操作的页面,不是 chromedriver,通过以下方法
# 获取当前窗口句柄
h = self.driver.current_window_handle
all_h = self.driver.window_handles
# 循环判断是否与首页句柄相等
for i in all_h:
if i != h:
self.driver.switch_to.window(i)
直接报错:WebDriverException: Message: Method has not yet been implemented。

小暖ljj 回复

好吧,爱莫能助了,最好自己发个帖子,把代码、界面截图和日志文件发出来,好让大家针对性的帮你分析。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册