Appium常用操作之混合应用H5上下文切换
1.native&web&hybrid简介
目前基本所有的移动互联网app可以分为三类:Native App(原生应用),Hybrid App(混合应用)和Web App(网页应用)。
Native App是基于智能手机操作系统API,使用原生语言编写的App;
Web App是基于Web的系统或应用,使用的是HTML,JavaScript和CSS等网页相关语言编写的App;
Native App则是融合了Native和Web,使用原生语言编写应用的外壳然后在其中内嵌网页语言编写的内容信息;
- 三种模式对比:
优点 | 缺点 | |
Native | 能够访问智能设备提供的所有功能; 支持离线工作; 更好的运行速度,性能和总体用户体验; 支持丰富的图形,动画和更好的渲染效果; |
开发成本较高; 维护,更新成本高; |
Web | 适用范围广,跨平台; 开发成本较低; 可以方便,快速地部署; 用户随时访问最新版本; |
用户体验差(加载慢,费流量); 图形和动画渲染效果差; 不能调用系统相关功能(相机,GPS等); |
Hybrid | 可调用智能设备相关功能; 部分支持离线功能; 维护,更新较为方便; |
用户体验较差; 图形和动画渲染效果较差; |
怎么样分辨一个app是native还是web的呢?
判断方法:
-
看断网的情况
把手机的网络断掉。然后点开页面。然后可以正常显示的东西就是原生写的。
-
布局边界
可以打开开发者选项中的显示布局边界,页面元素很多的情况下布局是一整块的是h5的,布局密密麻麻的是原生控件。页面有布局的是原生的否则为h5页面。
-
加载的方式
如果在打开新页面导航栏下面有一条加载的线的话,这个页面就是H5页面,如果没有就是原生的。
2、Hybird自动化解决方案
我们之前所使用的的API都是针对于原生的应用而言的,如果是web页面就不能采取这些api来定位元素,而现在我们最常见的应用就是hybird混合应用。
appium原生的页面是通过android/ios官方提供的API,web的部分是通过webview组件渲染出来的,所以Hybird自动化主要是解决webview这部分自动化。
现在主流的android系统都是大于4.4的了,所以我们采取UIAutomator+ChromeDriver模式:
原生部分走UIAutomator,webview部分走Chromedriver,两者结合混搭,从而实现Hybird自动化,要求如下:
1.android4.4设备
2.手机和电脑连接,开启USB调试模式,保证能够通过adbserver查看到设备名;
3.webview必须为debug模式(这点需要app对应的开发加上)
4.PC端和手机端安装google Chrome浏览器(尽量保持版本一致);
5.电脑网络支持翻墙
说明:如果是公司研发的产品可以让开发人员在app源码中将webviewdebug模式打开:在Android SDK API>=19的情况下,在源码中添
加 webview.setWebContentsDebuggingEnabled(true) 这一段代码即可。(如果使用的是
模拟器,则无需修改源码)
3.Hybird自动化脚本开发
一、识别webview
1.用定位工具查看页面,发现页面上有些区域无法定位到,如下图左边红色区域,只能定位到这个大框框,红色框里面的元素是无法识别的。
2.这时候可以查看元素属性,如右图它的class属性,上面写着WebView,那毫无疑问这种页面就是webview了。
二、contexts
1.context是中文翻译是上下文,环境,当然学过selenium的同学,也可以理解为句柄(handle),其实是一回事,反正知道是两个不同的环境就行了。
2.先获取页面是contexts环境,如下图红色区域,获取的是一个list列表:
NATIVE_APP:这个就是native,也就是原生的
WEBVIEW_com.xxxx :这个就是webview
3.当看到打印出来有下图两个,就说明获取到webview的context了(当然也有的app有坑,可能明明有webview,却通过contexts获取不到, 那是开发没打开webview调试)
三、切换到webview
1.要想操作webview上的元素,第一步需要切换环境(跟selenium的切换iframe,切换handle思路是一样)
2.切换方法:switch_to.context(参数是webview的context)
由于第二步已经获取到contexts是一个list对象,取这个list的第二个参数就行,也就是contexts[1],也可以说是倒数第一个也就是contexts[-1]
四、切回native
最后注意在webview上操作完后,如果要定位原生的元素,还需要先回到native上操作,这时候需要先切回来,切回native有两个方法:
方法一:driver.switch_to.context("NATIVE_APP") # 这个NATIVE_APP是固定的参数
方法二:driver.switch_to.context(contexts[0]) # 从contexts里取第一个参数
示例代码如下:
#前面一系列操作,打开了H5页面 #等待web页面出现 WebDriverWait(driver,10,1).until(EC.visibility_of_element_located(MobileBy.CLASS_NAME,"android.webkit.WebView")) #获取当前的上下文 contexts=driver.contexts print("当前所有的contexts:",contexts) #切换上下文,切换到webview time.sleep(1) #也可以通过名称来切换 #driver.switch_to.context("WEBVIEW_com.baidu.yuedu") driver.switch_to.context(contexts[-1]) #获取web内容 source=driver.page_source # 切回native driver.switch_to.context(contexts[0]) # driver.switch_to.context("NATIVE_APP") # 这样也是可以的
4.Hybird问题点总结
使用driver.contexts只获取到native app的情况:
1.测试手机/模拟器不是安卓4.4以上的版本,因为在安卓4.4以下的版本的webview没有使用Chrome内核,直邮在selendroid模式中才支持4.4以下的内核,这时就需要通过selendroid辅助我们,在desiredCapbilities中添加如下配置:
desired_caps["automationName"]="Selendroid"
2.程序中使用的webview不是chrome内核,而appium只支持chrome内核,所以appium就不能获取该webview的context;
例如腾讯公司的X5内核,具体切换定位方法见文章:https://www.cnblogs.com/123blog/p/12624007.html
3.在脚本执行的时候回出来下面的错误日志信息:
[Chromedriver] Error: Failed to start Chromedriver session: An unknown server-side error occurred while processing the command. Original error: unknown error: Chrome version must be >= 49.0.2623.0 [Chromedriver] (Driver info: chromedriver=2.22.397933 (1cab651507b88dec79b2b2a22d1943c01833cc1b),platform=Windows NT 6.1.7601 SP1 x86_64)
根据chrome浏览器版本去下载对应的Chromedriver.exe(要与webview的版本保持匹配,即webview版本号代表了chrome浏览器的版本号),将驱动文件放到对应appium目录下。
对应chrome浏览器和Chromedriver版本参考:https://www.cnblogs.com/123blog/articles/12623967.html