Java-Appium app实战详解
appium是一个移动端的自动化测试框架,可用于测试原生应用,移动网页应用和混合应用,并且是跨平台的。可用于IOS和Android操作系统adb是用来连接安卓手机和PC端的工作,adb命令可以让用户在PC对手机端进行各种操作。
·
一、appium
1、简介:
appium是一个移动端的自动化测试框架,可用于测试原生应用,移动网页应用和混合应用,并且是跨平台的。可用于IOS和Android操作系统
2、appium设计理念
- appium 设计理念和工作原理我就不再自己编写啦 这里分享两篇笔者觉得写的很不错的文章,大家可以看看
https://zhuanlan.zhihu.com/p/85197280
3、appium工作原理
4、环境依赖
- java 1.8版本
- Android sdk
- Node js(>=10版本),npm(>=6版本)
- appium-desktop
- Appium java client
appium server 本地cmd安装:
#先安装node.js
https://nodejs.org/en/download/
# 安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 安装appium最新版本
cnpm install -g appium --registry=https://registry.npm.taobao.org
# 选择版本号安装
cnpm install appium@版本号
# 安装appium-doctor
npm install -g appium-doctor
5、appium常用Capability
官方文档:
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md
// 使用的操作系统
capabilities.setCapability("platformName","Android");
// 设备名称
capabilities.setCapability("deviceName","mate40");
// app包名
capabilities.setCapability("appPackage","com.tencent.wework");
// app应用名
capabilities.setCapability("appActivity",".launch.LaunchSplashActivity");
// 是否重置app信息 比如权限授予
capabilities.setCapability("noReset",true);
// 对app进行完全重置,清除app中所有的数据
capabilities.setCapability("fullReset",true);
// 执行结束后不关闭app
capabilities.setCapability("dontStopAppOnReset","true");
// 使用的automation版本 新版本appium默认使用 UiAutomator2
capabilities.setCapability("automationName","UiAutomator2");
// 设置uuid唯一标识符 是设备的真是名称 使用 adb devices获取
capabilities.setCapability("uuid","devicesUUid");
// 自动统一app需要获取的权限 默认未true 不能与noreset公用
capabilities.setCapability("autoGrantPermissions","true");
// 等待发送命令时间 超过时间就会退出appium 默认为60秒
capabilities.setCapability("newCommandTimeout","60");
二、adb命令使用
1、adb简介:
adb是用来连接安卓手机和PC端的工作,adb命令可以让用户在PC对手机端进行各种操作
2、adb命令
adb --help: 查看帮助手册
adb devices: 检测链接到电脑的安卓设备
adb pull 手机路径 本地路径: 从手机中拉去信息到本地电脑中
adb push 本地路径 手机路径: 将信息从本地电脑中放到手机
adb shell reboot : 设备重启
adb shell: 登录shell,进入手机系统,在手机系统中可用Linux命令
adb install xxx.apk:安装 软件
adb install -r xxx.apk 保留数据和缓存文件,重新安装软件
adb uninstall 包名: 卸载应用
adb uninstall -k 包名:卸载应用但是保留数据和缓存文件
获取Activity的几种方式
mac:
adb logcat | grep ActivityManager
adb shell dumpsys activity activities | grep mFocusedActivity
aapt dumpsys badging com.android.chrome.apk |grep 'launchable-activity'
adb logcat ActivityManager:I | grep "cmp"
win:
adb shell dumpsys activity |findstr "mFocusedActivity":查看前台应用包名
adb logcat | findstr "ActivityManager" 可以查看包名和启动
adb logcat ActivityManager:I | findstr "cmp"
adb kill-server:终止adb服务
adb start-server:开启adb服务
adb shell pm list packages:列出所有包名
-f 列出所有apk路径及包名
-s 列出系统apk路径和包名
-3 列出用户apk路径及包名(用户自己安装的)
adb logcat:打印日志
adb shell am start -n 包名/入口:启动app
adb shell pm clear 包名:清除应用的数据和缓存
adb shell input tap x坐标 y坐标:点击坐标元素
三、Android
1、Android 七大布局
Android是通过容器的布局属性来管理子控件的位置关系,布局过程就是把界面上的所有控件根据间距大小,摆放在正确位置
- linearLayout(线性布局)
- RelativeLayout(相对布局)
- FrameLayout(帧布局)
- AbsoluteLayout(绝对布局)
- TableLayout(表格布局)
- GridLayout(网格布局)
- ConstraintLayout(约束布局)
2、Android 四大组件
- activity 与用户交互的可视化界面
- service 实现程序后台运行的解决方案
- content provider 内容提供者,提供程序所要数据
- broadcast recriver 广播接收器,监听外部事件的到来
3、常用控件
- TextView (文本控件)
- EditText (可编辑控件)
- Button (按钮)
- ImageButton (图片按钮)
- toggleButton (开关按钮)
- ImageView (图片控件)
- CheckBox (复选框控件)
- RadioButton (单选框控件)
4、控件基础
- Android应用层级结构与html不一样,是一个定制的xml
- app source 类似于dom,表示app的层级,代表界面里面所有的控件树的结构
- 每个控件都有它的属性,没有css属性
5、元素常用方法
- element.click() 点击
- element.send_keys() 输入
- element.set_value() 设置元素值
- element.clear() 清除元素内容
- element.is_displayed() 元素是否可见
- element.is_enabled() 元素是否可用
- element.is_selected() 是否被选中
- element.getLocation() 获取坐标
- element.get_attribute(attributeName) 获取属性
appium获取attribute流程:
- server从client获取到getAttribute请求
- server把请求发送给手机端运行bootstarp
- bootstarp调用相关方法从页面上获取到目标attribute
- bootstrap再将结果返回给appium-server
- 最后appium-server把获取到的结果返回给client
6、元素常见属性
- 文本 text 在python selenium中 文本是textContent
- 坐标 location 结果:{‘y’:y,‘x’:x}
- 获取高和宽 size 结果:{‘width’:y,‘height’:x}
java自动化
1、常用定位方法
- ID定位:优先使用该定位,但是app的id可能存在相同的情况
private By goToManageBtn = new By.ById("i6i");
- xpath定位:可进行相对复杂定位,效率不高。 (className=android.widget.TextView)
private By searchResult = new By.ByXPath("//android.widget.TextView");
- text定位:可通过xpath或UiAutomator来进行定位
private MobileBy addMemberBtn = new MobileBy.ByAndroidUIAutomator("new UiSelector().text(\"添加成员\")");
private By addMemberBtn = new By.ByXPath("//*[@text='添加成员']");
- UiAutomator定位:是一种强有力的定位方式,通过安卓原生的UiAutomator去查找元素 ,但是新版本已经弃用
// 通过content-desc
new MobileBy.ByAndroidUIAutomator("new UiSelector().description(\"content-desc属性\")");
// 通过className
new MobileBy.ByAndroidUIAutomator("new UiSelector().className(\"className\")");
// 通过resouseId
new MobileBy.ByAndroidUIAutomator("new UiSelector().resouseId(\"resouseId\")");
// 通过text包含文本
new MobileBy.ByAndroidUIAutomator("new UiSelector().textContains(\"text\")");
// 通过text文本开头
new MobileBy.ByAndroidUIAutomator("new UiSelector().textStarWith(\"text文本开头\")");
// 通过正则表达式
new MobileBy.ByAndroidUIAutomator("new UiSelector().textMatch(\"正则表达式\")");
// 通过多种属性组合 如:id+text
new MobileBy.ByAndroidUIAutomator("new UiSelector().resouseId(\"resouseId\").text(\"text\")");
// 层级选择 子类选择
new MobileBy.ByAndroidUIAutomator("new UiSelector().resourceId(\"resourceId\").childSelector(text(\"text\"))")
// 层级选择 兄弟节点
new MobileBy.ByAndroidUIAutomator("new UiSelector().resouseId(\"resouseId\").fromParent(text(\"text\"))")
- accessibility-id(content-desc)定位:只有在uiautomatorviewer启动程序能找到该属性
2、三大等待
一般页面上的元素呈现顺序:
- 首先出现页面title
- dom树出现 不完整
- css样式出现
- js出现,js特效执行
html文档是自上而下的加载的,js文件加载会堵塞html页面内容加载,可能就会导致页面出现后元素未加载出来,就会出现查找元素时超时报错,所以需要在找元素时加上等待。
- . 强制等待(不推荐使用):
Thread.sleep(milles)
- . 隐式等待:隐式等待是通过服务端等待,服务端每间隔一段时间就会去移动端查找元素是否存在,存在则返回给客户端,为全局等待。
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
- . 显式等待:显式等待是客户端的等待,客户端每间隔一段时间就去询问服务端,服务端再去移动端获取,效率没有隐式等待高但是可以根据不同条件进行等待。
WebDriverWait wait = new WebDriverWait(driver, Constant.WAIT_TIME);
wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
3、TouchAction事件
常用事件:
按键 | 描述 |
---|---|
press | 手势按下 |
release | 手势松开 |
move_to | 移动到 |
tap | 点击 |
wait | 等待 |
longPress | 长按 |
cancle | 取消 |
perform | 执行 |
示例
// 单点滑动-向下
// 1、先获取到手机页面尺寸
windowWidth = driver.manage().window().getSize().getWidth();
windowHeight = driver.manage().window().getSize().getHeight();
// 2、创建TouchAction对象
TouchAction touchAction = new TouchAction(driver)
// 3、创建Duration对象(滑动过程所需时间---单位为毫秒)
Duration duration = Duration.ofMillis(1000)
// 4、利用TouchAction对象添加动作并执行
touchAction.press(PointOption.point(
windowWidth/2,windowHeight*0.2)).waitAction(
WaitOption.waitOption(duration )).moveTo(
PointOption.point(windowWidth/2,windowHeight*0.6))
.release().perform();
// 多点操作:多点操作就是两个单点操作同时进行(放大、缩小等操作)
// 放大操作:
// 1、先获取到手机页面尺寸
windowWidth = driver.manage().window().getSize().getWidth();
windowHeight = driver.manage().window().getSize().getHeight();
// 2、创建MultiTouchAction对象
MultiTouchAction mTouchAction = new MultiTouchAction(driver)
// 3、创建两个单点操作对象(TouchAction)
TouchAction touchAction01
= new TouchAction(driver).press(PointOption.point(
windowWidth*0.4,windowHeight*0.5)).waitAction(
WaitOption.waitOption(duration )).moveTo(
PointOption.point(windowWidth*0.2,windowHeight*0.5))
.release();
TouchAction touchAction02
= new TouchAction(driver).press(PointOption.point(
windowWidth*0.6,windowHeight*0.5)).waitAction(
WaitOption.waitOption(duration )).moveTo(
PointOption.point(windowWidth*0.8,windowHeight*0.5))
.release();
// 4、将单点操作添加到MultiTouchAction中
mTouchAction.add(touchAction01).add(touchAction02);
// 5、执行操作
mTouchAction.perform();
// 九宫格操作
移动到指定位置并点击
// 滑动到text=webview 的位置并进行点击
driver.findElement(AppiumBy.androidUIAutomator(
"new UiScrollable(new UiSelector().scrollable(true))"+
".scrollIntoView(new UiSelector().text('WebView'))"
)).click();
4、driver-api
1、切换app startActivity:
同个app可以切换到不同页面,不同app只能切换到app入口
// 创建一个Activity对象
Activity activity = new Activity(包名,入口);
// 调用startActivity方法跳转页面
driver.startActivity(activity);
2、发送键值事件
// 1、创建KeyEvent对象
KeyEvent key = new KeyEvent();
// 2、调用withKey方法加入键值
Key.withKey(AndroidKey.VOLUME_UP);
// 3、使用pressKey发送键值
Driver.pressKey(Key);
3、其他api:
- getPageSource(): 获取页面所有元素
- currentActivity(): 获取当前正常运行的activity
- getCapabilities():获取 Capabilities信息
- getDeviceTime():获取设备时间
- getDisplayDensity(): 获取设备DPI
- getAutomationName():获取Automation 名字 没有配置的话默认为null
- getOrientation():获取设备横竖状态
- resetApp():重置app状态
- isAppInsatlled():判断app是否已经安装
5、 ListView元素定位 滑动至元素可见
1、利用AndroidUIAutomator获取
Driver.findElementByAndroidUIAutomator(
“new UiScrollable(new UiSelector().scrollable(true).instance(0))
.scrollIntoView(new UiSelector().textMatches(\””+selector+”\”).instance(0))”)
.click();
2、可通过while循环滑动获取元素,直到获取到元素或到达页面底部
6、获取toast元素
// 先将automationName转换成UiAutomator2 默认为先automationName
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
// 获取toast方式只能通过xPath方式定位
// 可以通过点击后获取pageSource 在进行定位
Driver.getElement(By.xpath(“//*[contains(@text, ’tips’)]”)).getText();
7、断言
1、普通断言方式assert断言
2、hamcrest断言 该断言提供了大量“匹配器”方法,每个匹配器都设计用于执行特定比较。
断言在之前文章已经有介绍
以上就是本分享的内容 如有错误欢迎提出,后续会继续分享 混合应用自动化的、异常统一处理以及小程序自动化的内容
更多推荐
已为社区贡献4条内容
所有评论(0)