安装配置skd
修改安卓模拟器nox_adb.exe文件
ADB命令
基本命令
查看帮助
adb help
查看版本
adb version
查看adb的连接设备:
adb devices
参数 显示列表
无 所有应用
-f 显示应用关联的 apk 文件
-d 只显示 disabled 的应用
-e 只显示 enabled 的应用
-s 只显示系统应用
-3 只显示第三方应用
-i 显示应用的 installer
-u 包含已卸载应用
包名包含 字符串
该命令经常出现以下问题:
- offline —— 表示设备未连接成功或无响应;
- device —— 设备已连接;
- no device —— 没有设备/模拟器连接;
- List of devices attached 设备/模拟器未连接到 adb 或无响应
链接到夜神模拟器
adb connect 127.0.0.1:62001
# 如果连接不到的时候:先找到端口号
adb nodaemon server
# 在根据 端口号 找到进程的PID
netstat -ano | findstr "5037"
# 在进行清除此PID
taskkill /pid 22712 -f
# 然后调用 重启 或者手动重新联机即可
adb start-server
# 或者
adb connect 127.0.0.1:62001
杀进程
adb kill-server
adb start-server
查看当前的包名类名
adb shell dumpsys activity | find "mFocusedActivity"
打印日志
adb logcat
指定某个应用的日志
adb shell pm list packages tenc //模糊查询带有tenc字符的应用程序
//使用find或者grep来筛选应用日志,这里我拿微信来测试打印日志
adb logcat | grep com.tencent.mm
adb logcat | find "com.tencent.mm" //find后面需要加上“”引号
日志重定向
adb logcat > 你的文件路径.txt文件
adb logcat > D:\log\032801.txt
从手机拉取信息到本地电脑
adb pull <手机路径> <本地路径>
# 例如
adb pull /storage/emulated/0/Android/data/com.vphone.launcher/files/download D:\AndroidSdk
从本地拉取到手机中
adb pull <本地路径> <手机路径>
登录设备shell 模式
adb shell
解析apk安装包
D:\AndroidSdk\android-sdk-windows\tools 启动cmd并执行下列命令
aapt dump badging D:\AppTest\weixin.apk
# 并且查找 package 包名
aapt dump badging C:\Users\askbd\Downloads\jiakaobaodian.apk | findstr package
# 查找对应的包名
aapt dump badging C:\Users\askbd\Downloads\jiakaobaodian.apk | findstr launchable-activity
查看所有应用
adb shell pm list packages
???
adb nodaemon server
参数 含义
-l 将应用安装到保护目录 /mnt/asec
-r 允许覆盖安装
-t 允许安装 AndroidManifest.xml 里 application 指定 android:testOnly=“true” 的应用
-s 将应用安装到 sdcard
-d 允许降级覆盖安装
-g 授予所有运行时权限
安装app
adb install <安装包路径>
例如:
adb install C:\Users\askbd\Downloads\weixin.apk
查询当前运行app包名
adb shell dumpsys activity | find "mFocusedActivity"
# 检测包的信息
adb shell dumpsys package io.appium.settings
列出所有的包名
adb shell pm list packages
-s列出系统apk路径以及包名
-3列出用户apl路径以及包名
卸载app
adb uninstall <包名>
例如:
adb uninstall com.tencent.mm
启动App
adb shell am start -n 包名/入口
例如:
adb shell am start -n com.tencent.mm/com.tencent.mm.ui.LauncherUI
清除应用的数据和缓存
adb shell pm clear 包名
adb shell pm clear com.tencent.mm
坐标点击
adb shell input tap x轴坐标 y轴坐标
adb shell input tap 600 900
使用 Monkey 进行压力测试
monkey是android自带系统自带的程序,可以生成伪随机用户事件来模拟单击、触摸、手势等操作,可以对正在开发中的程序进行随机压力测试。
简单用法
// 命令,表示向 com.tencent.mm 程序发送 500 个伪随机事件,并且将日志指定位置保存
adb shell monkey -p com.tencent.mm -v 500 > 日志路径.txt
-v 是提升日志级别,最高可加三个-v
//示例输出
bash arg: -p
bash arg: com.tencent.mm
bash arg: -v
bash arg: 500
args: [-p, com.tencent.mm, -v, 500]
arg: "-p"
arg: "com.tencent.mm"
arg: "-v"
arg: "500"
data="com.tencent.mm"
Appium原理介绍
{
"deviceName": "127.0.0.1:62001 device",
"platformName": "Android",
"appPackage": "com.tencent.mm",
"appActivity": "com.tencent.mm.ui.LauncherUI"
}
页面布局
页面控件
ADB组件
API解析
# currentActivity 可以获取当前前台正在运行的类名
String actual = androidDriver.currentActivity();
# findElementByAndroidUIAutomator (如果找不到,必须把java版本配置到1.8)
xxxxxxxxx.findElementByAndroidUIAutomator("new UiSelector().text(\"北京\")");
元素定位
id定位
className定位
AccessibilityId定位
xpath定位
1.text常规定位:
比如我要用text属性的文本值定位,这时候只需要写成xpath表达式
xxxxxxxx.findElementByXPath("//android.widget.TextView[@text='北京']").click();
2.contains模糊定位
这种经常用于获取toast的时候,toast文本内容较长,可以采用contains包含部分文本的匹配方式。当然,可以用来模糊匹配上面的文本属性“同意并继续”
# 元素定位
agree_continue_xpath = "//*[@text='同意并继续']"
3.组合定位
比如xpath中同时包含class和text两个属性
# 元素定位
agree_continue_xpath = "//*[@class='android.widget.Button' and @text='同意并继续']"
4.层级定位
使用lazy uiautomatorviewer,可以看到底下有个fullIndexXpath,这种是全路径的形式,也是层级的形式
# 元素定位
agree_continue_xpath = "//android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.Button[2]"
Android UIAutomator定位
android uiautomator原理是通过android 自带的android uiautomator的类库去查找元素,其实和appium的定位一样,或者说他比appium的定位方式更佳多以及更佳适用,它也支持id、className、text、模糊匹配等进行定位。
1 text定位
ele = self.driver.find_element_by_android_uiautomator('new UiSelector().text("请输入手机号")')
ele.send_keys("123")
1
2 text模糊定位
模糊定位故名思义,通过text的部分信息就能够进行定位,我们直接看代码:
ele = self.driver.find_element_by_android_uiautomator('new UiSelector().textContains("请输入手")')
ele.send_keys("123")
1
3 textStartsWith定位
# 以text什么开始
driver.find_element_by_android_uiautomator('new UiSelector().textStartsWith("请输入")')
1
4 textMatches 正则匹配查找
textMatches故名思义就是通过正则的来进行查找定位,他也是通过text的属性来进行正则匹配,我们直接看代码:
ele = self.driver.find_element_by_android_uiautomator('new UiSelector().textMatches("^请输入手.*")')
ele.send_keys("123")
1
5 resourceID定位
resourceId定位和appium封装好的id定位是一样的,只是这里将写法变成了uiautomator的写法而已,看下面代码
ele = self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("cn.com.open.mooc:id/et_phone_edit")')
ele.send_keys('234')
1
6 resourceIDMatches 定位
通过id进行正则匹配定位
ele = self.driver.find_element_by_android_uiautomator('new UiSelector().resourceIdMatches(".+et_phone_edit")')
ele.send_keys('234')
1
7 className定位
通过调用android uiautomator使用className进行定位
ele = self.driver.find_element_by_android_uiautomator('new UiSelector().className("android.widget.EditText")')
ele.send_keys('234')
1
8 classNameMatches定位
通过className正则匹配进行定位
ele = self.driver.find_element_by_android_uiautomator('new UiSelector().classNameMatches (".*EditText")')
ele.send_keys('234')
1
9 组合定位
#组合定位
self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/tab_name").text("我的")').click()
1
# 组合定位,一般组合用id,class,text这三个属性会比较好一点
# id+class 属性组合
id_class = 'resourceId("com.xyh.commerce:id/ll_personal").className("android.widget.LinearLayout")'
driver.find_element_by_android_uiautomator(id_class).click()
10 父子关系、兄弟关系定位
#父子关系定位
self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/title_container").childSelector(text("股票"))')
1
#兄弟关系定位
self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/title_container").fromParent(text("股票"))')
11 滚动查找
#滚动查找
self.driver.find_element_by_android_uiautomator('new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("查找的元素文本").instance(0));')
1
LazyUiAutomatorViewer
使用lazy uiautomatorviewer,可以看到底下有个uiaSelector,将其拷贝到代码
# 元素定位
agree_continue_android_uiautomator = "new UiSelector().className(\"android.widget.Button\").textContains(\"同意并继续\").resourceId(\"com.baidu.searchbox:id/positive_button\")"
WebDriverWait(driver, 10, 1).until(EC.visibility_of_element_located((MobileBy.ANDROID_UIAUTOMATOR, agree_continue_android_uiautomator)))
driver.find_element_by_android_uiautomator(agree_continue_android_uiautomator).click()
appium与selenium元素定位之比较
框架 常用的元素定位方式 备注
appium id, className, AccessibilityId, xpath, AndroidUIAutomator 对于h5页面,也支持selenium的name, link text, css等定位方式
selenium id, className, name, tag name, link text, paratial link text, xpath ,css
元素等待类型
强制等待
- 固定的等待时间:
- Thread.sleep()
隐式等待
- 针对全局元素设置等待时间
androidDriver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);
显式等待
- 针对某个元素设置等待时间
WebDriverWait
手势操作
滑动
- java-client 5.0之前版本有提供滑动的API ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
startx,starty # 起始点坐标的x , y轴值 endx , endy # 终止点坐标的x, y轴值 duration # 从起始点到终止点的滑动时间 androidDriver.swipe(startx,starty,endx,endy,duration);
Maven项目配置
Java Client包地址
eclipse中安装TestNG
方法1:直接Help-> Eclipse Marketplace 下面搜索testng,出来后直接点Install
方法2:使用archive方式安装
先下载eclipse-testng: http://dl.bintray.com/testng-team/testng-eclipse-release/
使用java代码启动app程序
前提:
提前在模拟器中安装好app应用
连接好模拟器 adb connect 127.0.0.1:62001
打开好Appium 并运行
package com.test.firstAppium;
import java.net.MalformedURLException;
import java.net.URL;import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;import io.appium.java_client.android.AndroidDriver;
public class AppiumTest {
//此方法为启动App应用程序
public static void main(String[] args) throws MalformedURLException {
//1创建配置对象
DesiredCapabilities desiredCapabilities =new DesiredCapabilities();
//2.添加配置
//deviceName: 可以找到我们测试的设备
desiredCapabilities.setCapability(“deviceName”,“127.0.0.1:62001”);
//paltformName:测试平台Android or ios
desiredCapabilities.setCapability(“platformName”,“Android”);
//appPackage : 找到想要的测试App
desiredCapabilities.setCapability(“appPackage”,“com.handsgo.jiakao.android”);
//appActivity : 测试app入口
desiredCapabilities.setCapability(“appActivity”,“com.handsgo.jiakao.android.splash.Login”);//3创建驱动 //传入连个参数 //第一个参数:Appium通讯地址 //第二个参数:配置对象 AndroidDriver<WebElement> androidDriver =new AndroidDriver<WebElement>( new URL("http://127.0.0.1:4723/wd/hub"),desiredCapabilities); }}
使用java脚本启动驾考宝典app
package com.test.firstAppium;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Driver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import io.appium.java_client.android.AndroidDriver;
public class AppiumTest {
public static AndroidDriver<WebElement>androidDriver;
//此方法为启动App应用程序
public static void main(String[] args) throws MalformedURLException, InterruptedException {
//1创建配置对象
DesiredCapabilities desiredCapabilities =new DesiredCapabilities();
//2.添加配置
//deviceName: 可以找到我们测试的设备
desiredCapabilities.setCapability("deviceName","127.0.0.1:62001");
//paltformName:测试平台Android or ios
desiredCapabilities.setCapability("platformName","Android");
//appPackage : 找到想要的测试App
desiredCapabilities.setCapability("appPackage","com.handsgo.jiakao.android");
//automationName:uiautomator2来解决输入框输入不了数据
//自动化引擎
desiredCapabilities.setCapability("unicodeKeyboard", "true");
desiredCapabilities.setCapability("resetKeyboard", "true");
// desiredCapabilities.setCapability("automationName","uiautomator2");
//appActivity : 测试app入口
desiredCapabilities.setCapability("appActivity","com.handsgo.jiakao.android.splash.Login");
//3创建驱动
//传入连个参数
//第一个参数:Appium通讯地址
//第二个参数:配置对象
androidDriver =new AndroidDriver<WebElement>(
new URL("http://127.0.0.1:4723/wd/hub"),desiredCapabilities);
//调用驾考这个方法
testJiaKao();
}
public static void testJiaKao() throws InterruptedException {
//等待元素加载完毕
Thread.sleep(5000);
//点击同意并继续
androidDriver.findElementById("com.handsgo.jiakao.android:id/btn_agree").click();
Thread.sleep(10000);
//点击夏考宝典申请获得以下权限 的知道了
androidDriver.findElementById("com.handsgo.jiakao.android:id/permission_box").click();
androidDriver.findElementById("com.handsgo.jiakao.android:id/permission_btn").click();
Thread.sleep(2000);
//1.找到定位城市文本,并且点击
androidDriver.findElementById("com.handsgo.jiakao.android:id/cityTv").click();
Thread.sleep(5000);
//2.找到城市搜索框并且输入"北京"
androidDriver.findElementById("com.handsgo.jiakao.android:id/edt_search_q").sendKeys("北京");
//3 选择北京
androidDriver.findElementById("com.handsgo.jiakao.android:id/item_title").click();
//4找到小车并点击
androidDriver.findElementById("com.handsgo.jiakao.android:id/itemCar").click();
Thread.sleep(4000);
//5点击报名状态为 已报名驾校
androidDriver.findElementById("com.handsgo.jiakao.android:id/registeredTv").click();
//点击性别为男
androidDriver.findElementById("com.handsgo.jiakao.android:id/maleTv").click();
//6.找到下一步,并且点击
androidDriver.findElementById("com.handsgo.jiakao.android:id/okBtn").click();
Thread.sleep(2000);
//1选择暂不绑定
androidDriver.findElementById("com.handsgo.jiakao.android:id/tv_un_bind").click();
}
}
下拉刷新
package com.test.firstAppium;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.testng.reporters.jq.Main;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Driver;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.WebDriverWait;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.functions.ExpectedCondition;
import io.appium.java_client.touch.WaitOptions;
import io.appium.java_client.touch.offset.PointOption;
public class AppiumTestShuaXin {
public static AndroidDriver<WebElement> androidDriver;
@BeforeTest
public void setUp() throws MalformedURLException, InterruptedException {
// 1创建配置对象
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
// 2.添加配置
// deviceName: 可以找到我们测试的设备
desiredCapabilities.setCapability("deviceName", "127.0.0.1:62001");
// paltformName:测试平台Android or ios
desiredCapabilities.setCapability("platformName", "Android");
// appPackage : 找到想要的测试App
desiredCapabilities.setCapability("appPackage", "com.handsgo.jiakao.android");
// noReset: 不清除应用的数据启动测试 ture表示不清除; 默认false表示清除
desiredCapabilities.setCapability("noReset", "true");
// automationName:uiautomator2来解决输入框输入不了数据
// 自动化引擎
// desiredCapabilities.setCapability("unicodeKeyboard", "true");
// desiredCapabilities.setCapability("resetKeyboard", "true");
desiredCapabilities.setCapability("automationName", "uiautomator2");
// appActivity : 测试app入口
desiredCapabilities.setCapability("appActivity", "com.handsgo.jiakao.android.splash.Login");
Thread.sleep(10000);
// 3创建驱动
// 传入连个参数
// 第一个参数:Appium通讯地址
// 第二个参数:配置对象
androidDriver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), desiredCapabilities);
// 设置隐式等待
// androidDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
// @Test(enabled = false)
@Test
public void testJiaKao() throws InterruptedException {
Thread.sleep(10000);
// 下拉刷新 7.3.0
TouchAction<?> touchAction = new TouchAction<>(androidDriver);
//
// 把原始的坐标转化成pointOption类型的
PointOption startPointOption = PointOption.point(356, 594);
PointOption endPointOption = PointOption.point(356, 794);
// 把原始的时间装换成Duration类型
Duration duration = Duration.ofMillis(800);
// 在转化成WaitOptions类型的
WaitOptions waitOptions = WaitOptions.waitOptions(duration);
touchAction.press(startPointOption).waitAction(waitOptions).moveTo(endPointOption).release();
// 让我们的滑动生效
touchAction.perform();
}
@AfterTest
public void tearDown() {
// 当测试用例测试完毕,我们销毁驱动
androidDriver.quit();
}
}
错误合集
夜神模拟器 冲突问题
把D:\AndroidSdk\android-sdk-windows\platform-tools\adb.exe 文件
修改名称为 =nox_adb=
D:\安卓模拟器\Nox\bin\nox_adb.exe
uiautomatorviewer 定位提示Error obtaining UI hierarchy
这是因为工具不太稳定导致的
- 首先检查你的jdk版本是不是1.8或1.8以下,因为1.9的jdk不兼容uiautomatorviewer
- 进入任务管理器,停止adb.exe,然后在CMD界面输入adb connect xxx,再输入adb devices后,再点击uiautomatorview.bat文件去运行
- 再多试几次还是不行的话,建议使用appium自带的元素定位去定位,毕竟这个uiautomatorviewer不稳定
或者 杀进程:
1.sudo adb kill-server
2.sudo adb start-server
Unable to start adb server: error: protocol fault (couldn’t read status): Connection reset by peer
大多数情况是5037端口被占用。5037为adb默认端口。
解决办法:
查看哪个程序占用了adb端口,结束这个程序,然后重启adb就好了。
使用命令:=netstat -aon|findstr “5037”= 找到占用5037端口的进程PID。
使用命令:=tasklist|findstr “5440”= 通过PID找出进程。
调出任务管理器,找到这个进程,结束进程。
使用命令:adb start-server 启动adb就行了