混合应用WebView自动化经验总结
一、概述
EufySecurity App,除了原生App的应用模块外,还有一些Html页面功能模块,主要包括有Explore商城模块、H5提示等,是一款由原生App+WebView组成的混合应用。
下面主要介绍Explore商城模块自动化实现过程遇到的一些经验和坑,如何在原有自动化框架上实现混合应用之间的App Webview自动化。
二、Web元素定位
1、Android
google提供了webview组件的调试工具devtools,通过devtools可以直接在pc端的chrome上直接调试app上的html内容,前提是webview必须打开debug模式。
debug模式可以让App开发在webview的对象实例添加调试模式即可,这里略过。
一切就绪后,PC端USB连接安卓手机,使用谷歌浏览器打开如下页面即可。
chrome://inspect/#devices
2、IOS
1. IOS直接使用Mac Safari浏览器进行调试。
- 在手机设置里,找到Safair浏览器,在高级里启用Web检查器;
- Mac上Safair浏览器,在偏好设置高级选项底部勾选“在菜单栏中显示开发菜单”;
- 手机连接Mac,点击Mac上的Safair浏览器,在开发选项下拉菜单中,找到手机名称对应的html页面即可进入调试器;
2. Google Chrome浏览器调试方法
- 使用brew安装 ios-webkit-debug-proxy
brew install ios-webkit-debug-proxy
若上面的命令不有效,尝试下面的命令安装
brew uninstall --force libimobiledevice ios-webkit-debug-proxy
brew install --HEAD libimobiledevice ios-webkit-debug-proxy
- 安装成功后,在终端输入下面的命令
ios_webkit_debug_proxy -f chrome-devtools://devtools/bundled/inspector.html
若有问题,报错Could not connect to lockdownd. Exiting.: Permission denied,可输入下面的命令,再次尝试
sudo chmod -R 777 /var/db/lockdown/
- 保持终端命令连接状态,在chrome浏览器中打开 localhost:9221,点击真机选项;
- 作App跳转到JS页面,下面两种方式均可进入调试器:
(1)在Mac的chrome中刷新页面,选中要打开的html连接,右键点击“复制链接地址”,新建标签页,在地址栏粘贴地址,按enter键进入;
(2)直接在谷歌浏览器地址栏中输入chrome://inspect/#devices,点击Target下方的inspect进入;
备注:
(1)手机上也要安装谷歌浏览器,否则终端可能无法连接到真机;
(2)复制JS页面地址时,不要用cmd+c快捷键,要右键单击“复制链接地址”,然后新建标签页,粘贴地址打开;
总结:
两种浏览器相比较,虽然Safair调试器打开方便,但容易卡住,有时无法查看JS的变量值,甚至打断点会闪退,建议使用Google Chrome浏览器调试方法。
三、WebView自动化
1、Appium Webview相关链接
http://appium.io/docs/cn/writing-running-appium/web/hybrid/
2、appium desired_capabilities
Android
'chromeOptions': {
'androidProcess': 'com.oceanwing.battery.cam', # 驱动H5自动化, 防止卡住
'w3c': False
},
'recreateChromeDriverSessions': True, # 移动至非web程序时,是否杀掉chromeDriver
IOS
'startIWDP': True, # 使用ios-webkit-debug-proxy
# 'nativeWebTap': True, # 添加这个webview点击元素会错乱,坑之一
'webkitResponseTimeout': 10000, # webkit 超时时间设置
3、切换上下文
webview
contexts = self.driver.contexts # 获取所有context
webview = contexts[-1] # 一般新webview为list最后一个
self.driver.switch_to.context(webview) # 切换到webview
NATIVE_APP
self.driver.switch_to.context('NATIVE_APP') # 一般原生的都为NATIVE_APP
四、坑路
1、IOS获取Contexts存在延时
解决办法:等待获取多几次才会拿到
for i in range(5):
contexts = self.driver.contexts
webview = contexts[-1]
if webview != 'NATIVE_APP':
self.driver.switch_to.context(webview)
break
else:
time.sleep(2)
2、处于Webview模式下,无法用appium原生方法截图
解决办法:切出Webview再截图
def get_screenshot(self):
"""兼容h5截图"""
src = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
path = src.replace("/src", "")
image_floder = '{}/image'.format(path)
if not os.path.exists(image_floder):
os.makedirs(image_floder)
name = datetime.now().strftime('%m%d%H%M%S')
path_name = u'{}/{}.png'.format(image_floder, name)
current_c = self.driver.current_context
if 'NATIVE_APP' not in current_c: # 如果不是NATIVE_APP,切换成NATIVE_APP截图, 截完图再还原context
webview = self.driver.contexts
lenght = len(webview)
for i in range(lenght):
if webview[i] == 'NATIVE_APP':
self.driver.switch_to.context(webview[i])
self.driver.get_screenshot_as_file(path_name)
self.driver.switch_to.context(current_c)
else:
self.driver.get_screenshot_as_file(path_name)
return path_name
3、IOS webview页面部分元素点击无效
网上也有一堆这样问题,逐一尝试任无效
解决办法一:刷新按钮使用NATIVE_APP元素DOM中可以获取到,切回NATIVE_APP点击
解决办法二:使用鼠标方法点击
def click_h5_back(self):
"""H5页面返回按钮点击"""
try:
if self.platform == GlobalVar.IOS:
self.switch_to_native_app()
self.click_element(LOCATOR.h5_back_btn)
self.switch_to_webview()
else:
self.click_element(LOCATOR.h5_back_btn)
return True
except NoSuchElementException:
return False
def tap_h5(self, locator):
el = self.get_element(locator)
tas = TouchActions(self.driver)
tas.tap(el).perform()
4、webview页面嵌套frame需切换页面进去
解决办法:
self.driver.switch_to.frame(el) # 切到frame页面
self.click_element(LOCATOR.video_play)
self.driver.switch_to.parent_frame() # 退出frame页面
5、webview页面无法实现滑动动作
解决办法:切回NATIVE_APP进行滑动操作
self.switch_to_native_app() # 用原生app才能滑动
self.swipe_by_element('left', 0.8, 0.2, 0.25)
self.switch_to_webview()
6、IOS 刷新按钮值存在3秒,Appium获取元素存在时延,display:false无法点击
解决办法:获取相关元素坐标,推演坐标点击
def drop_page(self):
"""刷新页面"""
self.switch_to_native_app()
if self.platform == GlobalVar.IOS:
scroll_l = self.driver.find_element(By.XPATH, '//XCUIElementTypeOther[@name="Horizontal scroll bar, 1 page"]/preceding-sibling::XCUIElementTypeOther').location
scroll_h = self.driver.find_element(By.ID, 'Horizontal scroll bar, 1 page').location
update_x = scroll_l['x']
update_y = scroll_h['y'] - 15
self.tap(self.top_x, self.top_y)
print(update_x, update_y)
self.tap(update_x, update_y)
else:
self.swipe_by_element('down', 0.38, 0.68, 0.5)
self.switch_to_webview()
原 Google 链接:
https://docs.google.com/document/d/1I4C3a4ao3X9K-7Qzdu6F_fAKc1TwvlrETNRQo9rGNvw/view