进阶之Hybrid
Hybrid应用,简而言之就是指Native应用里内嵌了WebView的应用。此类应用从14年开始普遍流行,从技术发展和业务契合度的角度来看,Hybrid带来了许多好处和变化,比如使App本身更加轻便,使许多热更技术变得可行等等。但这也给我们做App的自动化带了许多难度和瓶颈。
在Appium出现之前,能实现Hybrid自动化的框架并不多。而Selendroid
就是其中一个。
而Appium所应用到的技术,其中一项也正是包含了Selendroid
模式。
Appium下的Hybrid解决方案
- 1、基于
Selendroid
模式 - 2、基于
UiAutomator
+Chromedriver
模式
这两种模式各有优劣:
Selendroid模式
- 支持Android2.3+
- 支持Hybrid自动化
- 运行速度快
- 无法使用许多手势API
- apk包需要重签名
- 无法跨进程
Appium模式
- 支持Android4.4以上设备
- 支持Hybrid自动化
- 可跨进程
- apk包无需重签名
- 源码中webview必须为debug模式(真机)
很明显,我们从以上两个分析可以看出,Appium模式其实是更加完善,对于运行稳定性和拓展性优势是要比较明显的。目前的Android市场份额,已经逐渐向高端转化,不出半年,也会变成4.4~6.0的天下了。所以,这个模式正在从劣势变为优势。
但是上面提到的webview必须为debug模式是什么意思呢?
基于UIAutomator+Chromedriver的实践
使用chromedriver
来做hybrid的自动化我们有几个前提条件必须解决:
- 1、准备好Android4.4或以上的手机;
- 2、将Webview设置为debug模式;
- 设置方法:在Android SDK API>=19的情况下,在源码中添加
webview.setWebContentsDebuggingEnabled(true)
这一段代码即可。(如果使用的是模拟器,则无需修改源码)
- 设置方法:在Android SDK API>=19的情况下,在源码中添加
Android混合应用自动化的关键API
实际上,Appium模式下,实现混合应用的自动化的原理很简单,Native部分走UIAutomator,Webview部分走Chromedriver,两者结合混搭,从而实现Hybrid的自动化。
那我们到底如何做到在UIAutomator
和Chromedriver
之间灵活地游走呢?
除了准备工作要做好,还有几个关键的概念你需要清楚:
- context
- window_handle(一般很少用到)
我们通过切换当前context
对象,来让Appium
认识自己当前处于哪一个状态里面,对于webview
的context
对象,可能会打开多个网页,那我们还需要通过切换window_handle
对象来让Chromedriver
认识自己当前是打开的哪个页面。
那么,刚刚提到的两个概念,就是我们学习的重点。
解读Sample-Code
Talk is very cheap。 相信看完上面的东西,许多同学还是一头雾水。 还是从看源码解释要来得清楚一点。
我们从sample-code-androidWebViewTest.java可以看到:
public class AndroidWebViewTest {
private AppiumDriver<WebElement> driver;
@Before
public void setUp() throws Exception {
// set up appium
File classpathRoot = new File(System.getProperty("user.dir"));
File app = new File(classpathRoot, "../../../apps/selendroid-test-app.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName","Android Emulator");
//automationName必须为Appium,或者该参数不填
capabilities.setCapability("automationName","Appium");
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("appPackage", "io.selendroid.testapp");
capabilities.setCapability("appActivity", ".HomeScreenActivity");
driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
@After
public void tearDown() throws Exception {
driver.quit();
}
@Test
public void webView() throws InterruptedException {
WebElement button = driver.findElement(By.id("buttonStartWebview"));
button.click();
Thread.sleep(6000);
//获取当前页面的所有Context对象,其中就会包含Native和Webview的对象。
Set<String> contextNames = driver.getContextHandles();
for (String contextName : contextNames) {
System.out.println(contextName);
//遍历获取下来的context对象,若发现context对象包含WEBVIEW字样的时候,就切换到该对象下
if (contextName.contains("WEBVIEW")){
driver.context(contextName);
}
}
//然后就是Webview中的操作,webview下的自动化定位方式与Selenium中web的定位是一样的。
WebElement inputField = driver.findElement(By.id("name_input"));
inputField.sendKeys("Some name");
inputField.submit();
}
}
我在上面标注了4个关键的注释,请认真阅读。
其中,相比于单纯的Native测试,Hybrid测试会多两道工序,那就是:
- 1、获取当前contexts对象
- 2、切换到webview的context对象下
接下来后续的操作都是跟Native下相差无几。
注意点
- 当我们在Webview下操作完毕了以后,若想要操作Native下的元素,则需要重新切换context对象到Native下,就跟你切换到webview下是一样的。
App中WebView元素的定位方式
有同学会问,Native的所有元素都可以通过uiautomatorviewer获取到,那webview里的元素我们有办法或者有工具能够帮助我们定位吗?
答案肯定是有的。
那就是chrome浏览器的inspector
。
使用方法:
- 1、手机连接上电脑,并打开App,打开需要定位的Webview的页面
- 2、电脑上打开Chrome,地址栏输入
chrome://inspect
- 3、点击devices标签,此时你会看到你设备上对应的App的包名
- 4、点击包名旁边的
inspect
,就会进入chrome的调试工具,在这个调试工具就可以获取当前webview的所有元素了。