Java-Appium app实战详解

一、appium

1、简介:

appium是一个移动端的自动化测试框架,可用于测试原生应用,移动网页应用和混合应用,并且是跨平台的。可用于IOS和Android操作系统

2、appium设计理念

3、appium工作原理

4、环境依赖

  1. java 1.8版本
  2. Android sdk
  3. Node js(>=10版本),npm(>=6版本)
  4. appium-desktop
  5. 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流程:

  1. server从client获取到getAttribute请求
  2. server把请求发送给手机端运行bootstarp
  3. bootstarp调用相关方法从页面上获取到目标attribute
  4. bootstrap再将结果返回给appium-server
  5. 最后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、三大等待

一般页面上的元素呈现顺序:

  1. 首先出现页面title
  2. dom树出现 不完整
  3. css样式出现
  4. 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断言 该断言提供了大量“匹配器”方法,每个匹配器都设计用于执行特定比较。
断言在之前文章已经有介绍

以上就是本分享的内容 如有错误欢迎提出,后续会继续分享 混合应用自动化的、异常统一处理以及小程序自动化的内容

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值