# 移动应用测试
# 查看包名:
方案一:如果你应用已经安装在手机上了,可以直接打开手机上该应用,进入到你要操作的界面,然后执行 (注:一定要用 cmd 运行,powershell 会报参数不正确):
adb shell dumpsys activity recents | find "intent={"
会出现如下信息:
intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher3/.Launcher}
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 pkg=tv.danmaku.bili cmp=tv.danmaku.bili/.MainActivityV2}
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.flysilkworm/.app.activity.FrameworkActivity}
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.settings/.Settings}
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10800000 cmp=io.appium.settings/.Settings}
C:\WINDOWS\System32>adb shell dumpsys activity recents | find "intent={"
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=tv.danmaku.bili/.MainActivityV2}
intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher3/.Launcher}
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.flysilkworm/.app.activity.FrameworkActivity}
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.settings/.Settings}
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10800000 cmp=io.appium.settings/.Settings}
其中 cmp=tv.danmaku.bili/.MainActivityV2 就是 / 之前是包名(appPackage),之后是 appActivity
方案二:如果是已有 apk 在电脑上
aapt dump badging D:\Desktop\软测\iBiliPlayer-bili.apk | find "package"
aapt dump badging D:\Desktop\软测\iBiliPlayer-bili.apk | find "launchable-activity"
会出现如下信息:
1、
C:\WINDOWS\System32>aapt dump badging D:\Desktop\软测\iBiliPlayer-bili.apk | find "package"
package: name='tv.danmaku.bili' versionCode='6430500' versionName='6.43.0'
2、
C:\WINDOWS\System32>aapt dump badging D:\Desktop\软测\iBiliPlayer-bili.apk | find "launchable-activity"
launchable-activity: name='tv.danmaku.bili.MainActivityV2' label='' icon=''
1、的 name 是包名,2、的 name 是 appActivity(tv.danmaku.bili.MainActivityV2,
可以省略 tv.danmaku.bili)
方案三:算是方案一的进阶吧 (推荐)
adb shell dumpsys window w |findstr \/ |findstr name=
# 或者
adb shell dumpsys activity activities | findstr mFocusedActivity
# 在 UI Automator Viewer.bat 中运行一次 Python 就连不上的问题:
特别提示:如果按照 Python 模板写,按 q 退出可以避免连不上的问题,相关代码如下
q = input('input q to quit') | |
if q == 'q': | |
driver.quit() |
方案一:重启模拟器
方案二:重启 adb(推荐方案二,因为方案一很慢 ( ̄_ ̄|||))
adb kill-server & adb start-server |
方案三:appium 重连(原因:运行后 appium 占用指定端口与本身需要的端口冲突导致)
# Python 中测试基本语法:
参考语法文档:http://www.byhy.net/tut/auto/appium/02/
# 根据 id | |
driver.find_elements_by_id("android:id/button2") #既可以找多个元素也可以找单个元素 | |
# 点击事件 | |
driver.find_element_by_id("cn.xuexi.android:id/comm_head_xuexi_score").click() | |
# tap 点按(bounds 属性,停留的时间) | |
driver.tap([(850,1080)],300) | |
# 发送文字事件(resource-id) | |
sbox = driver.find_element_by_id('search_src_text') | |
sbox.send_keys('Doyoudo') | |
driver.press_keycode(AndroidKey.ENTER) | |
# 根据 class 元素 | |
driver.find_elements_by_class_name('android.widget.TextView') | |
# 根据 ACCESSIBILITY ID(content-desc 属性) | |
driver.find_element_by_accessibility_id('找人') | |
# 根据 Xpath | |
driver.find_element_by_xpath('//ele1/ele2[@attr="value"]') | |
# 模拟滑动 | |
driver.swipe(start_x=x, start_y=y1, end_x=x, end_y=y2, duration=800) | |
# 按键 | |
# 输入回车键,确定搜索 | |
driver.press_keycode(AndroidKey.ENTER) | |
# 返回 | |
driver.press_keycode(AndroidKey.BACK) | |
# 隐式等待 设置缺省等待 10 秒时间(不推荐) | |
driver.implicitly_wait(10) | |
# 强制等待 等 5 秒(推荐) | |
time.sleep(5) | |
# 显示等待 (有点多直接看链接吧) | |
https://blog.csdn.net/sinat_41774836/article/details/88965281 | |
# 打开通知栏,返回直接 BACK 键 | |
driver.open_notifications() | |
# 截屏手机,并且下载到指定目录中 | |
import os | |
os.system('adb shell screencap /sdcard/screen3.png && adb pull /sdcard/screen3.png') |
关于 TouchAction 类与 MultiAction 类的相关用法 (九宫格解锁可以用 touchaction)
联合查询:
# xpath 方式: 可以联合 @resource-id 属性和 @text 文本属性来下定位 | |
driver.find_element_by_xpath("//*[@resource-id='com.taobao.taobao:id/tv_scan_text'][@text='扫一扫']").click() | |
# 内嵌 Java 方式: 后面可以一直.name () 这种方式添加(调用 UI Automator API 的 java 代码,实现最为直接的自动化控制。) | |
code = 'new UiSelector().text("追番").resourceId("tv.danmaku.bili:id/tab_title")' | |
ele = driver.find_element_by_android_uiautomator(code) | |
ele.click() | |
# 具体 java 代码 来自谷歌 Android 文档: | |
https://developer.android.google.cn/training/testing/ui-automator | |
#常用列表 | |
text(String) # 对应 text | |
resourceId(String) # 对应 resource-id | |
description(String) # 对应 content-desc | |
className(String) # 对应 class | |
index(int) # 对应 index | |
instance(int) # 是匹配的结果所有元素里面的第几个元素 | |
textContains(String) # 根据文本包含什么字符串 (与 text 连用) |
注:
ele = driver.find_element_by_android_uiautomator( | |
'new UiSelector(). className(" android.widget. TextView"). textContains("白月黑羽").instance(4)' | |
) | |
print(ele.text) | |
等同于下方代码 | |
eles = driver.find_elements_by_android_uiautomator( | |
'new UiSelector(). className("android.widget. TextView"). textContains("白月黑羽")' | |
) | |
print(eles[4].text) |
# Python 基础模板(Python 的第三方库 appium-python-client)
from appium import webdriver | |
from appium.webdriver.extensions.android.nativekey import AndroidKey | |
desired_caps = { | |
'platformName': 'Android', # 被测手机是安卓 | |
'platformVersion': '5', # 手机安卓版本 | |
'deviceName': 'HUAWEI', # 设备名,安卓手机可以随意填写 | |
'appPackage': 'tv.danmaku.bili', # 启动 APP Package 名称 | |
'appActivity': '.MainActivityV2', # 启动 Activity 名称 | |
'unicodeKeyboard': True, # 使用自带输入法,输入中文时填 True | |
'resetKeyboard': True, # 执行完程序恢复原来输入法 | |
'noReset': True, # 不要重置 App | |
'newCommandTimeout': 6000, | |
'automationName' : 'UiAutomator2' | |
# 'app': r'd:\apk\bili.apk', | |
} | |
try: | |
# 连接 Appium Server,初始化自动化环境 | |
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) | |
# 设置缺省等待时间 | |
driver.implicitly_wait(5) | |
# 青少年保护 | |
iknow = driver.find_elements_by_id("text3") | |
if iknow: | |
iknow.click() | |
driver.find_element_by_id("expand_search").click() | |
sbox = driver.find_element_by_id('search_src_text') | |
sbox.send_keys('Doyoudo') | |
driver.press_keycode(AndroidKey.ENTER) | |
eles = driver.find_elements_by_id("title") | |
for ele in eles: | |
print(ele.text) | |
ele.click() | |
q = input('input q to quit') | |
if q == 'q': | |
driver.quit() | |
except Exception as err: | |
print('An exception happened: ' + str(err)) | |
q = input('error q to quit') | |
if q == 'q': | |
driver.quit() |
# 自定义 Python 模板
import time | |
from appium import webdriver | |
from appium.webdriver.common.touch_action import TouchAction | |
from appium.webdriver.extensions.android.nativekey import AndroidKey | |
desired_caps = { | |
'platformName': 'Android', | |
'platformVersion': '7', | |
'deviceName': 'HUAWEI', | |
'appPackage': 'tv.danmaku.bili', # adb shell dumpsys activity activities | findstr mFocusedActivity | |
'appActivity': '.MainActivityV2', # 启动 Activity 名称 | |
'unicodeKeyboard': True, | |
'resetKeyboard': True, | |
'noReset': True, | |
'newCommandTimeout': 6000, | |
'automationName': 'UiAutomator2' | |
} | |
def id(a): | |
return driver.find_element_by_id(a) | |
def ids(a): | |
return driver.find_elements_by_id(a) | |
def xpath(a): | |
return driver.find_element_by_xpath(a) | |
def xpaths(a): | |
return driver.find_elements_by_xpath(a) | |
def desc(a): | |
return driver.find_element_by_accessibility_id(a) | |
def class_names(a): | |
return driver.find_elements_by_class_name(a) | |
def tap(a, b, c, d): | |
return driver.tap([(a, b), (c, d)], 100) | |
def back(): | |
driver.press_keycode(AndroidKey().BACK) | |
def enter(): | |
driver.press_keycode(AndroidKey().ENTER) | |
def move(x, y, m, n): | |
driver.swipe(start_x=x, start_y=y, end_x=m, end_y=n, duration=800) | |
def long_press(el1, el2): | |
action = TouchAction(driver) | |
action.long_press(el1).move_to(el2).release().perform() | |
try: | |
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) | |
driver.implicitly_wait(10) | |
time.sleep(5) | |
q = input('input q to quit\n') | |
if q == 'q': | |
driver.quit() | |
except Exception as err: | |
print('An exception happened: ' + str(err)) | |
q = input('error q to quit') | |
if q == 'q': | |
driver.quit() |
# appium 测试 ui 界面模板 (就是 python 中的 desired_caps)注:这里内部必须都为双引号
{ | |
"platformName": "Android", | |
"platformVersion": "57", | |
"deviceName": "HUAWEI", | |
"appPackage": "cn.xuexi.android", | |
"appActivity": "com.alibaba.android.rimet.biz.SplashActivity", | |
"unicodeKeyboard": true, | |
"resetKeyboard": true, | |
"noReset": true, | |
"newCommandTimeout": 10000, | |
"automationName": "UiAutomator2" | |
} |
# adb 基本命令
先附上参考文档:
https://www.wanandroid.com/blog/show/2310
查看当前连接设备
adb devices
如果发现多个设备
adb -s 设备号 其他指令
查看顶部 Activity
windows 环境下:
adb shell dumpsys activity | findstr "mFocusedActivity"
Linux、Mac 环境下:
adb shell dumpsys activity | grep "mFocusedActivity"
查看日志
adb logcat
安装 apk 文件
adb install xxx.apk
推荐使用覆盖安装:
adb install -r xxx.apk
卸载 App
adb uninstall com.zhy.app
如果想要保留数据,则
adb uninstall -k com.zhy.app
传递文件
往手机 SDCard 传递文件
adb push 文件名 手机端SDCard路径
从手机端下载文件
adb pull /sdcard/xxx.txt
启动 Activity
adb shell am start 包名/完整Activity路径
清除 APP 数据
adb shell pm clear com.example.packagename
注:该命令清除掉 APP 的缓存,还能把 APP 的数据给清空
查看所有 App 的名称
adb shell pm list packages
注:该命令可以查看手机上的 APP 名称。可以在后面加上 -f ,这样还能显示该 APP 的路径,即:
adb shell pm list packages -f
或者adb shell pm path <PACKAGE>
列出第三方应用:
adb shell pm list packages -3