WebView操作
这节课我们会来介绍下WebView的操作,之前我们介绍的都是原生控件的操作,WebView和其他原生控件的操作有点差别,WebView里面包含的控件用之前的定位方式没办法直接定位到,需要借助其他工具来查看其里面具体控件的定位方式,然后通过xpath或css定位方式来进行WebView里面控件的定位。
那么什么样的控件是WebView控件呢,可以打开开源中国应用,然后点击进入资讯详情页面,打开uiautomatorviewer工具查看下,如果控件类型是android.webkit.WebView的控件就是WebView控件,如下所示:
包含WebView这里面的子控件用之前的定位方式不好定位到,这时候可以打开谷歌浏览器,然后输入chrome://inspect
然后点击下图所示的inspect按钮
在出现的页面点击下图所示的有个箭头的按钮,然后在窗口左侧点击想定位的地方,接着右侧html代码视图里就会自动定位到你在左侧所选的控件,然后鼠标右键选择Copy Xpath,就可以获得你想定位的控件的xpath了,我们就可以通过这个路径来进行webview里面子控件的定位
如果这个工具不可以用,看下你是否符合它所要求的如下的几个前置条件:
在具体编写WebView操作之前我们需要来添加几个WebView处理的方法,WebView需要想进行句柄切换,切换完才能进行WebView内的操作,我们在Helper添加如下方法:
代码语言:javascript复制 //webview相关操作的API
//通过xpath定位
public WebElement findByXpath(String xpath){
return driver.findElementByXPath(xpath);
}
//获取当前的句柄
public Set<String> getContextHandlers(){
return driver.getContextHandles();
}
//切换执行环境
public void content(String name){
driver.context(name);
}
因为切换webview句柄的方法很多测试脚本都会使用到,这时候可以在PageCommon里添加如下方法:
代码语言:javascript复制 public void switchToWebView(){
Set<String> handlers = helper.getContentHandlers();
for(String handler : handlers){
System.out.println("===============" handler);
}
helper.content("XXXA");
}
public void switchToNative(){
helper.content("XXXB");
}
上面的切换到WebView句柄或者原生的句柄的字符串我们还不能知道是什么,先用"XXXA"和"XXXB"设置下去,等下在测试脚本里先调用下switchToWebView方法,在这个方面里会输出当前的所有句柄,然后我们在根据输出的内容来替换这两个参数值。
这时候可用新建一个测试类WebViewTest来进行WebView操作的示例,编写如下测试代码:
代码语言:javascript复制import appium.common.BasicTestCase;
import org.testng.annotations.Test;
public class WebViewTest extends BasicTestCase {
@Test
public void testWebView() throws Exception {
//点击首页第1行
pageHelper.getPageNews().clickNewsItem(2);
Thread.sleep(3000);
pageHelper.getPageCommon().switchToWebView();
}
}
执行下这个脚本,然后看下控制台输出:
得到WebView和native的句柄后更新PageCommon为如下所示:
代码语言:javascript复制 public void switchToWebView(){
Set<String> handlers = helper.getContentHandlers();
for(String handler : handlers){
System.out.println("===============" handler);
}
helper.content("WEBVIEW_net.oschina.app");
}
public void switchToNative(){
helper.content("NATIVE_APP");
}
假设我们需要获取第一段的内容,可以在PageNewsDetail添加如下两个方法:
代码语言:javascript复制 //根据传递的xpath查找第一段的控件
public WebElement getWebViewFirstLine(String xpath){
return helper.findByXpath(xpath);
}
//获取第一段控件的内容
public String getWebViewFirstLineContent(String xpath){
return helper.getText(getWebViewFirstLine(xpath));
}
然后通过Chrome inspect得到的XPath为:/html/body/div/p[1](这个值根据上面介绍的方法更新成你自己取到的值),编写如下代码:
代码语言:javascript复制package appium.testcases;
import appium.common.BasicTestCase;
import org.testng.annotations.Test;
public class WebViewTest extends BasicTestCase {
@Test
public void testWebView() throws Exception {
//点击首页第1行
pageHelper.getPageNews().clickNewsItem(2);
Thread.sleep(3000);
pageHelper.getPageCommon().switchToWebView();
String content = pageHelper.getPageNewsDetail().getWebViewFirstLineContent("/html/body/div/p[1]");
System.out.println(content);
}
}
执行这个脚本可能会出现如下的错误:
说明你使用的Chrome driver的版本和你的Chrome版本不匹配,我们可以去如下的URL下载匹配的版本的Chrome driver,然后在我们的脚本里指定使用这个版本的driver就可以避免这种错误了
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md
这个文档里列出了不同的Chrome所匹配的driver
根据操作系统选择对应的压缩包下载,下载完后解压缩,然后拷贝chromedriver文件到测试工程根目录下。查看我使用的模拟器版本为51.0.xxx所以我下载的是51.0对应连接的驱动。接着修改测试父类,然后指定Chrome driver使用的是根目录下的这个driver,更新完后的父类如下所示:
代码语言:javascript复制package appium.common;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import java.io.File;
import java.net.URL;
public class BasicTestCase {
//声明静态的对象引用driver
static AppiumDriver driver;
private Helper helper;
public PageHelper pageHelper;
@BeforeMethod
public void setUp() throws Exception {
File app = new File(System.getProperty("user.dir"), "AUT/osc.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", "My Android Device");
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("appPackage", "net.oschina.app");
capabilities.setCapability("appActivity", "net.oschina.app.AppStart");
capabilities.setCapability("noReset", true);
capabilities.setCapability("unicodeKeyboard", true);
File chromeDriverPath = new File(System.getProperty("user.dir"));
//如果是windows就是.exe的,Mac直接是chromedriver
capabilities.setCapability("chromedriverExecutable",chromeDriverPath.getAbsolutePath() "/chromedriver.exe");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
helper = new Helper(driver);
pageHelper = new PageHelper(helper);
//跳转到我的设置页面
pageHelper.getPageCommon().goToMySettingsTab();
//判断是否是登录状态,是的话就退出,不是的话就不做处理
if("aotu12345aotu".equals(pageHelper.getPageMySettings().getNickName())){
pageHelper.getPageMySettings().clickSettingsBtn();
pageHelper.getPageSettings().clickLogout();
}
//回到首页,每个测试脚本的入口就是首页
pageHelper.getPageCommon().goToHomeTab();
}
@AfterMethod
public void tearDown() throws Exception {
driver.quit();
}
//添加获取driver对象引用的方法
public static AppiumDriver getDriver(){
return driver;
}
}
再次执行下脚本可以发现成功打印出WebView文本内容了。