准备条件
(1)准备一台系统版本5.0以上的安卓手机或者安卓模拟器
(2)安装一个辅助工具(pc端安装):uc-devtool(UC开发者工具,不需要翻墙),uc-devtool安装成功-》选择设置->勾选 本地Devtools inpsector资源
参考文章:https://www.cnblogs.com/yyoba/p/9969394.html
uc-devtool作用: 用来帮助定位app内嵌套的web页面元素信息
(3)被测试的app->需要打开Web调试开关->如何打开开关:
第一种方式:让开发在app源代码中加入一行代码(开发知道在哪里添加)-》再重新打包给到测试
WebView.setWebContentDebuggingEnabled(true);
webview(其实就是手机自带的系统应用)
负责web页面展示,解析,渲染web页面,其实就是微型的浏览器(帮助第三方app来展示web页面)
如下图使用appium无法定位到具体的元素信息,选择元素-》选中的是整块区域
webview每个手机都有这个应用,是以一个apk存在手机里面的,如何查看手机是否有webView?
手机-》设置->应用->全部
点击可以查看版本
问题: 可以使用文章text进行定位,但是text会变,所以这里需要借助uc-devtool获取元素定位信息
开发步骤
(1)uc开发者工具识别web页面的元素信息
打开uc-devtool: 设置-》勾选
没有打开app时,如下图没有检测到webView
进入到app主页(由于主页不是一个web页面,所以也没有检测到webView)
进入到web页面(柠檬社区),如下图,检测到了webView
下图中的:com.lemon.lemonban是app的包名
127.0.0.1:62001 ->是当前连接的设备名
74.0.3627.136是webView的版本
上图点击 inspect即可进入deBug控制台
如下图(其实就是根f12效果差不多),这样就可以使用web自动化提供的xpath等方式进行元素定位了
(2)开发脚本:
原生和web面需要切换context才能进行元素定位。
Context是在编写Android程序经常使用到的对象,意思为上下文对象。原生和网页属于不同的context
@Test
public void test() throws InterruptedException {
//1.主页点击 柠檬社区
androidDriver.findElementByAndroidUIAutomator("new UiSelector().text(\"柠檬社区\")").click();
//2.等待web页面加载完成
//这里不能使用隐式等待(不会生效)->因为:这里不是找元素,而是进行context切换,所以不会生效,只能用硬性等待
Thread.sleep(8000);
//3.获取到当前状态所有的context
Set contextHandles = androidDriver.getContextHandles();
//打印出来看看-》打印结果:[NATIVE_APP,WEBVIEW_com.lemon.lemonban]
System.out.println(contextHandles);
//4.切换context-》根据web页面对应的context名字进行切换
androidDriver.context("WEBVIEW_com.lemon.lemonban");
Thread.sleep(2000);
//5.web页面元素定位
androidDriver.findElement(By.xpath("//a[@title=\"App 抓包提示网络异常怎么破?\"]")).click();
}
执行上面代码。如果报错,请看下面的注意(5)
注意
(1) 原生页面对应的context->是NATIVE_APP
不管你是主页还是登录页,只要是原生的页面,对应的context就是NATIVE_APP
(2)Web页面对应的context->是 WEBVIEW_com.lemon.lemonban
(3)打开app之后默认是在原生的context中,所以如果要定位web页面中的元素,需要切换context
(4)context切换之后,对web页面元素进行元素定位,为什么依然使用androidDriver,而不是( ie,firefox,chrome对应的driver呢)-->这是因为:Appium自带chromedriver,内部会进行driver驱动的替换,会把原来的androidDriver替换成chromedriver->为什么不是 IE,firrfox的driver呢,因为安卓系统是chrome开发的,webView也是chrome开发的,所以自动替换的就是chromeDriver
(5)webView和chromedriver版本不对应-》上面代码执行console会报下面错误
io.appium.java_client.NoSuchContextException: An unknown server-side error occurred while processing the command. Original error: No Chromedriver found that can automate Chrome '74.0.3729'. See https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md for more details.
Build info: version: '3.12.0', revision: '7c6e0b3', time: '2018-05-08T14:04:26.12Z'
appium报错日志如下:
根据报错信息可以知道:webView和chromedriver版本不匹配导致的
解决办法:
(1)找到appium自带的chromeview安装路径:
查看版本:
(2)模拟器查看系统自带的webview版本:
手机设置-》应用-》全部
(3)查看版本对照表
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md
appium自带的chromedriver版本是:75 ,模拟器自带的webView版本是74
参考版本对照表:webview71对应chromedriver是2.46 ,没有webview74版本,不过我们这里先下载2.46的试试看(下载完成后,将原来的chromedriver覆盖更新即可):结果发现是还是报凑
ChromeDriver 2.39 and newer require adb version 1.0.38 or newer. Run 'adb version' in your terminal of the host device to find your version of adb.
上面的报错信息说的是:
ChromeDriver 2.39及更高版本需要adb 1.0.38或更高版本。在主机设备的终端中运行“adb version”以查找adb的版本。
下图发现我的adb版本太低【1.0.36】【这里的adb用的是模拟器中的adb,因为之前sdk 自己的adb和模拟器中的adb版本不对应导致adb connect连接失败-》解决办法:将sdk中的adb替换成模拟器中的adb】
现在需要怎么解决呢?-》升级adb版本:将模拟器中adb换成sdk中的adb,sdk还用自己的adb
adb替换ok,需要重启adb,重启命令:adb kill-server,重启完adb后,再输入adb devices ,adb就会自动起来
再重新执行代码:发现context切换成功,下面代码可以定位到元素。
androidDriver.findElement(By.xpath("//a[@title=\"App 抓包提示网络异常怎么破?\"]")).click();
注意:这里为什么不是对webview进行升级而是替换chromeDriver呢?
因为:手机自带的webview升级很麻烦
(6)当回到原生页面进行测试时,需要将context切换回来
@Test
public void test() throws InterruptedException {
// 1.主页点击 柠檬社区
androidDriver.findElementByAndroidUIAutomator("new UiSelector().text(\"柠檬社区\")").click();
// 2.等待web页面加载完成
// 这里不能使用隐式等待(不会生效)->因为:这里不是找元素,而是进行context切换,所以不会生效,只能用硬性等待
Thread.sleep(8000);
// 3.获取到当前状态所有的context
Set contextHandles = androidDriver.getContextHandles();
// 打印出来看看-》打印结果:[NATIVE_APP,WEBVIEW_com.lemon.lemonban]
System.out.println(contextHandles);
// 4.切换context-》根据web页面对应的context名字进行切换
androidDriver.context("WEBVIEW_com.lemon.lemonban");
Thread.sleep(2000);
// 5.web页面元素定位
androidDriver.findElement(By.xpath("//a[@title=\"App 抓包提示网络异常怎么破?\"]")).click();
// 6.回到主页
// 6.1当回到原生页面中进行元素定位时,context需要切换回来(由于左上角x是在原生页面里面,需要需要切换,否则定位不到)
androidDriver.context("NATIVE_APP");
// 6.2定位到x按钮->退出
androidDriver.findElement(By.className("android.widget.ImageButton")).click();
// 6.3定位确定按钮-》确定 退出到主页
androidDriver.findElement(By.id("com.lemon.lemonban:id/tv_sure")).click();
}
如果context不切换,就会报如下错误:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"class name","selector":"android.widget.ImageButton"}
app中使用浏览器打开web页面,代码怎么写?
(1)如果使用的浏览器是手机系统自带的apk
那么如何获取浏览器apk的包名和启动入口呢?-》解决办法:将手机中的apk拉取到pc端
(2)再使用aapt解析apk的包名和启动入口
(3) 地址栏是原生的 用Androiddriver sendkeys方法 再输入enter键操作
androidDriver.get(url)这种是不可以的