Hybrid App,俗称混合应用,是介于 Web App 和 Native App 两者之间的一种 App 形式,Hybrid App 利用了 Web App 和 Native App 的优点,通过一个原生实现的 Native Container 展示 HTML5 的页面。更通俗的讲法可以归结为,在原生移动应用中嵌入了 Webview,然后通过该 Webview 来访问网页,Hybrid App 具有维护更新简单,用户体验优异以及较好的跨平台特性,是目前主流的移动应用开发模式
webview是android系统提供的能够显示网页的系统控件,Android4.4以下的版本,webview底层实现是使用webkit内核,Android4.4以上版本,采用chromium作为系统webview底层支持,API没有改变,支持HTML5,CSS3,javascript
webkit for webview | chromium for webview | 备注 | |
---|---|---|---|
HTML% | 278 | 434 | http://html5test.com/ |
远程调试 | 不支持 | 支持 | Android4.4版本以上支持 |
内存占用 | 小 | 大 | 相差20M左右 |
WebAudio | 不支持 | 支持 | Android4.45.0以上支持 |
WebGL | 不支持 | 支持 | Android4.45.0以上支持 |
WebRTC | 不支持 | 支持 | Android4.45.0以上支持 |
chromedriver和mapping.json的资源整理了一下,打包上传了,下载地址,包含所有版本的chromedriver和版本对照的json文件,下载完成后在脚本中直接使用:chromedriverExecutableDir和chromedriverChromeMappingFile参数进行引用即可
由于大多数应用商店的应用webview的开关的都是关闭的,在这里以appium官方提供的demo为例,进行简单的脚本示例。
appium-demo下载地址
配置测试设备和驱动,启动appium-demo
desired_caps = {
"platformName": "android",
"appium:deviceName": "b1f37e8e",
"appium:appPackage": "io.appium.android.apis",
"appium:appActivity": ".ApiDemos",
"chromedriverExecutableDir": "/Users/test/tools/chromedriverdir",
"chromedriverChromeMappingFile": "/Users/test/PycharmProjects/test_appium/testcase/mapping.json"
}
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'Views').click()
webview = "WebView"
self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, f'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("{webview}").instance(0));').click()
进入webview页面后直接去定位操作元素是无法成功的,这时候需要由原生页面切换至webview页面,使用driver的context方法
print(self.driver.contexts)
# 切换上下文,由原生切换至webview
self.driver.switch_to.context(self.driver.contexts[-1])
self.driver.find_element(By.XPATH, '//*[@id="i_am_a_textbox"]').send_keys("this is a test message")
完整代码如下:
from time import sleep
import pytest
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.common.by import By
class TestHybrid:
def setup(self):
desired_caps = {
"platformName": "android",
"appium:deviceName": "b1f37e8e",
"appium:appPackage": "io.appium.android.apis",
"appium:appActivity": ".ApiDemos",
"chromedriverExecutableDir": "/Users/gaozeyu/tools/chromedriverdir",
"chromedriverChromeMappingFile": "/Users/gaozeyu/PycharmProjects/test_appium/testcase/mapping.json"
}
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 设置隐式等待
self.driver.implicitly_wait(10)
def teardown(self):
self.driver.quit()
def test_hybrid(self):
sleep(3)
self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'Views').click()
webview = "WebView"
self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, f'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("{webview}").instance(0));').click()
print(self.driver.contexts)
# 切换上下文,由原生切换至webview
self.driver.switch_to.context(self.driver.contexts[-1])
self.driver.find_element(By.XPATH, '//*[@id="i_am_a_textbox"]').send_keys("this is a test message")
# 窗口切换
print(self.driver.window_handles)
self.driver.find_element(By.XPATH, '//*[@id="i am a link"]').click()
print(self.driver.window_handles)
sleep(3)
if __name__ == 'main':
pytest.main()